Đã lâu rồi không viết một bài gì, nhân tiệc việc ở cty đang ít, mình có viết 1 bài làm seminar cho các thành viên trong team về việc tạo animation giữa các viewcontroller. Bài viết cũng chỉ là sự tổng hợp của các tut đã có trên mạng, mình chỉ cố viết lại theo cách đơn giản nhất để ai cũng có thể tiếp cận. Giờ public cho mọi người cùng thưởng thức.
Ngoài lề chút, hiện tại thì trên mạng có trang này http://samvlu.com/ viết về quá trình 100 ngày code swift và có bán bài giảng. Mình định chơi 1 trang tương tự nhưng open source. Hi vọng sẽ sớm ra mắt mọi người.
Giới thiệu
Bắt đầu từ IOS7, apple hỗ trợ tạo animation lúc chuyển viewcontroller. Quá trình chuyển đổi được hỗ trợ bao gồm:
- NavigationController
- TabbarController
- Presentations và dismiss
Mình sẽ tập trung vào custom animation push và pop với NavigationController. Với các phương thức chuyển viewcontroller khác thì làm tương tự.
Mô hình hóa
Giả sử bạn có 2 viewcontroller A và B, bây giờ bạn muốn push từ A sang B.
Đầu tiên, ta cần khởi tạo transtion và xác định được 2 viewcontroller cần di chuyển, lúc này A đang được chứa bởi container(là view chứa để control việc di chuyển)
Tiếp theo add viewcontroller B vào container đang chứa A.
Cuối cùng là thực hiện animation chuyển đổi giữa 2 màn hình, quá trình kết thúc khi A được remove khỏi container
Implement
Để thực hiện được mô hình trên, ta sử dụng những protocol sau
UINavigationControllerDelegate
Protocol có 2 method giúp ta xác định được cách thức transition
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController NS_AVAILABLE_IOS(7_0);
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
Hàm đầu tiên dùng để tạo animation khi touch vào màn hình, trả về object implement UIViewControllerInteractiveTransitioning.
Hàm thứ hai xác định cách thức push/pop khi ta click action (next/back) trên thanh navigation bar, trả về object implement UIViewControllerAnimatedTransitioning. Các params giúp ta xác định được fromVC là viewcontroller nào, toVC là viewcontroller nào. Ở trường hợp di chuyển từ A sang B thì A là fromVC và B là toVC.
Cuối cùng là param operation, đây là enum gồm có 3 value để xác định trạng thái push hay pop
UINavigationControllerOperationNone,
UINavigationControllerOperationPush,
UINavigationControllerOperationPop,
UIViewControllerAnimatedTransitioning
có 2 phương thức
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
Để thực hiện animation ta cần 2 thông số, thông số đầu tiên là duration, hàm đầu tiên giúp ta xác định được điều đó. Phương thức thứ hai dùng để implement animation chuyển đổi. Trong hàm này ta cần đưa ra thông báo để biết được quá trình push/pop được hoàn thành
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
Example
Bước 1: Tạo ra object implement protocol UIViewControllerAnimatedTransitioning, trước hết xác định duration
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.25;
}
Định nghĩa một animation đơn giản
/**
* using example in
* https://www.objc.io/issues/5-ios7/view-controller-transitions/
*/
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
//1.
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
//2.
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0;
//3.
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.transform = CGAffineTransformMakeScale(0.1, 0.1);
toViewController.view.alpha = 1;
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformIdentity;
//4.
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
Phân tích chút nào:
- Bước 1: xác định toViewController và fromViewController
- Bước 2: add toViewController.view vào trong container
- Bước 3: thực hiện animation.
- Bước 4: thông báo animation kết thúc qua câu lệnh completeTransition
Bước 2:
Tạo object implement protocol UINavigationControllerDelegate, trong object này ta cần truyền vào object đã implement UIViewControllerAnimatedTransitioning trước đó.
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
// return your custom animation transition
}
Bước 3
Setting ở viewcontroller, như ở trên ta có viewcontroller A -> B. Ở A ta cần làm như sau trước khi push.
//1.
self.navigationController.delegate = /* your custom UINavigationControllerDelegate */;
//2.
[self.navigationController pushViewController:B animated:YES];
Ở bước này ta đã có thể push/pop với animation, nhưng để full service ta sẽ gắn thêm interactive animations. Tuy nhiên ở giới hạn bài viết này mình sẽ chỉ nói về animation cho push và pop. Bạn có thể tìm hiểu chi tiết hơn ở ví dụ của trang objc.io
Một animation mình làm
Bài viết có tham khảo