Ở kỳ này Techmaster sẽ giới thiệu qua về UIView tới các bạn học lập trình ios :

Lớp UIView cung cấp nhiều API để tạo hoạt hình. Trong bài viết tôi sẽ minh hoạ lập trình hoạt hình đối tượng UIView bằng mô hình con lắc đơn.

Có 2 cách hoạt hình đối tượng UIView:

1- Truyền block animation vào phương thức animateWithDuration

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion

Block animation sẽ chạy trong một khoảng thời gian duration, thay đổi thuộc tính của UIView (toạ độ, màu sắc, alpha) giữa điểm bắt đầu và kết thúc để cho iOS tự nội suy thuộc tính tại các thời điểm ở giữa.

Học lập trình ios online

Nội suy điểm giữa (x0,y0) và (x1,y1)

Học lập trình iPhone iPad

Con lắc đơn

#import "ViewController.h"
#define MAX_ANGLE M_PI_4 * 0.5
@interface ViewController ()
{
    NSTimer *_timer;
    double _angle;
    double _angleDelta;
}
@property (weak, nonatomic) IBOutlet UIImageView *pendulum;
@property (weak, nonatomic) IBOutlet UISlider *sliderAngle;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    CGSize size = self.pendulum.bounds.size;

    self.pendulum.layer.anchorPoint = CGPointMake(0.5, 0);
    self.pendulum.frame = CGRectMake((self.view.bounds.size.width - size.width)* 0.5, 20, size.width, size.height);
    
    _angle = 0.0;
    _angleDelta = 0.05;
    
}

- (void) startAnimation
{
    _timer = [NSTimer scheduledTimerWithTimeInterval: 0.1
                                              target: self
                                            selector: @selector(animatePendulum)
                                            userInfo: nil
                                             repeats: YES];
    [_timer fire];
}
- (IBAction)startStopAnimation:(UISwitch *)sender {
    if ([sender isOn]) {
        [self startAnimation];
        self.sliderAngle.enabled = NO;
    } else if (_timer.isValid) {
        [_timer invalidate];
         _timer = nil;
        self.sliderAngle.enabled = YES;
    }
    
}

- (void) animatePendulum
{
    _angle += _angleDelta;
    if ((_angle > MAX_ANGLE) | (_angle < - MAX_ANGLE)) {
        _angleDelta = - _angleDelta;
    }
    self.pendulum.transform = CGAffineTransformMakeRotation(_angle);
    NSLog(@"%3.2f - %3.2f", self.pendulum.center.x  , self.pendulum.center.y); //Chứng minh khi rotate center của UIView không đổi
    
}
- (IBAction)changeAngle:(UISlider *)sender {
    self.pendulum.transform = CGAffineTransformMakeRotation(MAX_ANGLE * sender.value);
}

@end

2- Tạo một timer để đều đặn chạy một hàm animation.

Với cách này, lập trình viên chủ động lập trình vị trí, thuộc tính của đối tượng UIView tại từng thời điểm. Đây là phương pháp hoạt hình chuyển động rất cổ điển nhưng vẫn hiệu quả cho nhiều nền tảng khác nhau.

- (void) startAnimation
{
    _timer = [NSTimer scheduledTimerWithTimeInterval: 0.1
                                              target: self
                                            selector: @selector(animatePendulum)
                                            userInfo: nil
                                             repeats: YES];
    [_timer fire];
}
- (void) animatePendulum
{
    _angle += _angleDelta;
    if ((_angle > MAX_ANGLE) | (_angle < - MAX_ANGLE)) {
        _angleDelta = - _angleDelta;
    }
    self.pendulum.transform = CGAffineTransformMakeRotation(_angle);
    NSLog(@"%3.2f - %3.2f", self.pendulum.center.x  , self.pendulum.center.y);    
}

Hàm animatePendulum sẽ là hàm đung đưa con lắc tại những thời điểm sát nhau 0.1 giây.

Đung đưa con lắc như thế nào?

Con lắc trong ứng dụng iOS này thực chất chỉ là một UIImageView, UIImageView thừa kế từ UIView. Tôi tự vẽ ảnh con lắc bằng Adobe Photoshop rồi xuất ra định dạng PNG, nhớ để transparent để sau này chúng ta có thể bổ xung hộp đồng hồ có vân gỗ.

Trong hàm animatePendulum, tôi tính toán lại giá trị góc _angle, rồi cập nhật lại thuộc tính transform của pendulum bằng CGAffineTransformMakeRotation. Chú ý biên độ lắc ở hai bên có giới hạn bằng góc MAX_ANGLE.

Các thuộc tính xác định vị trí, kích thước, góc quay của UIView

UIView có các thuộc tính xác định vị trí, kích thước, góc quay và tâm quay vật thể:
– Thuộc tính frame:CGRect (origin:CGPoint, size:CGSize).
– Thuộc tính transform:CGAffineTransform. Affine transform biến hình đồng dạng: gồm dịch chuyển tịnh tiến (translate), thay đổi kích cỡ (scale), xoay (rotate). Còn vài loại nữa affine transform nữa nhưng iOS chỉ hỗ trở 3 loại trên.
 - Khi lập trình xoay một đối tượng UIView, tâm quay là quyết định chuyển động. Có 2 thuộc tính là UIView.center và UIView.layer.anchorPoint.
UIView.center là toạ độ tâm của UIView trong hệ quy chiếu của UIView cha chứa UIView đó.
UIView.layer.anchorPoint xác định tâm quay của UIView . Ví dụ với một chiếc đĩa, tâm quay ở chính tâm đĩa khác hẳn với tâm quay ở mép đĩa.

Học lập trình iOS trực tuyến
Tài liệu tham khảo của đại học Standford

anchorPoint xác định tâm quay theo hướng x dải từ 0->1, hướng y dải từ 0->1. Như vậy dù vật thể có chiều dài khác chiều rộng thì vẫn coi là tỷ lệ 1:1. Mặc định anchorPoint ở tâm (0.5, 0.5).

Định lại tâm quay cho con lắc

Đối với trường hợp con lắc, nó xoay quanh điểm đầu của cán. Do đó cần phải đặt anchorPoint ở điểm (0.5, 0) ~ (x=0.5, y=0).
self.pendulum.layer.anchorPoint = CGPointMake(0.5, 0);

Toàn bộ mã nguồn tham khảo
Tải toàn bộ mã nguồn tại đây.

Khóa học lập trình di động tại Techmaster:

Để cài đặt MacOSX lên phần cứng không phải Apple liên hệ chuyên gia cài Hackintosh:

  • Nguyễn Minh Sơn: 01287065634
  • Huỳnh Minh Sơn: 0936225565
  • Website: caidatmacos.com