亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS如何自定義控制器轉場動畫push詳解

2019-10-21 18:42:52
字體:
來源:轉載
供稿:網友

前言

最近有些空閑時間,整理了下最近做的項目,本文主要介紹了關于iOS自定義控制器轉場動畫push的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

效果圖:

ios,push轉場動畫,控制器轉場動畫,自定義轉場動畫

iOS7 開始蘋果推出了自定義轉場的 API 。從此,任何可以用 CoreAnimation 實現的動畫,都可以出現在兩個 ViewController 的切換之間。并且實現方式高度解耦,這也意味著在保證代碼干凈的同時想要替換其他動畫方案時只需簡單改一個類名就可以了,真正體會了一把高顏值代碼帶來的愉悅感。

其實網上關于自定義轉場動畫的教程很多,這里我是希望同學們能易懂,易上手。

轉場分兩種Push和Modal,所以自定義轉場動畫也就肯定分兩種,今天我們講的是Push

自定義轉場動畫Push

首先搭建界面,添加4個按鈕:

- (void)addButton{   self.buttonArr = [NSMutableArray array];   CGFloat margin=50; CGFloat width=(self.view.frame.size.width-margin*3)/2; CGFloat height = width; CGFloat x = 0; CGFloat y = 0; //列 NSInteger col = 2; for (NSInteger i = 0; i < 4; i ++) {     x = margin + (i%col)*(margin+width);  y = margin + (i/col)*(margin+height) + 150;     UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];  button.frame = CGRectMake(x, y, width, height);  button.layer.cornerRadius = width * 0.5;  [button addTarget:self action:@selector(btnclick:) forControlEvents:UIControlEventTouchUpInside];  button.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0];  button.tag = i+1;  [self.view addSubview:button];  [self.buttonArr addObject:button]; }}

添加動畫:

- (void)setupButtonAnimation{   [self.buttonArr enumerateObjectsUsingBlock:^(UIButton * _Nonnull button, NSUInteger idx, BOOL * _Nonnull stop) {     // positionAnimation  CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];  positionAnimation.calculationMode = kCAAnimationPaced;  positionAnimation.fillMode = kCAFillModeForwards;  positionAnimation.repeatCount = MAXFLOAT;  positionAnimation.autoreverses = YES;  positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];  positionAnimation.duration = (idx == self.buttonArr.count - 1) ? 4 : 5+idx;  UIBezierPath *positionPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(button.frame, button.frame.size.width/2-5, button.frame.size.height/2-5)];  positionAnimation.path = positionPath.CGPath;  [button.layer addAnimation:positionAnimation forKey:nil];     // scaleXAniamtion  CAKeyframeAnimation *scaleXAniamtion = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.x"];  scaleXAniamtion.values = @[@1.0,@1.1,@1.0];  scaleXAniamtion.keyTimes = @[@0.0,@0.5,@1.0];  scaleXAniamtion.repeatCount = MAXFLOAT;  scaleXAniamtion.autoreverses = YES;  scaleXAniamtion.duration = 4+idx;  [button.layer addAnimation:scaleXAniamtion forKey:nil];     // scaleYAniamtion  CAKeyframeAnimation *scaleYAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.y"];  scaleYAnimation.values = @[@1,@1.1,@1.0];  scaleYAnimation.keyTimes = @[@0.0,@0.5,@1.0];  scaleYAnimation.autoreverses = YES;  scaleYAnimation.repeatCount = YES;  scaleYAnimation.duration = 4+idx;  [button.layer addAnimation:scaleYAnimation forKey:nil];    }];}

界面搭建好了:

ios,push轉場動畫,控制器轉場動畫,自定義轉場動畫

然后想在Push的時候實現自定義轉場動畫首先要遵守一個協議UINavigationControllerDelegate

蘋果在 UINavigationControllerDelegate 中給出了幾個協議方法,通過返回類型就可以很清楚地知道各自的具體作用。

//用來自定義轉場動畫- (nullable id)navigationController:(UINavigationController *)navigationController         animationControllerForOperation:(UINavigationControllerOperation)operation            fromViewController:(UIViewController *)fromVC             toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
//為這個動畫添加用戶交互- (nullable id)navigationController:(UINavigationController *)navigationController       interactionControllerForAnimationController:(id) animationController NS_AVAILABLE_IOS(7_0);

在第一個方法里只要返回一個準守UIViewControllerInteractiveTransitioning協議的對象,并在里面實現動畫即可

  • 創建繼承自 NSObject 并且聲明 UIViewControllerAnimatedTransitioning 的的動畫類。
  • 重載 UIViewControllerAnimatedTransitioning 中的協議方法。
//返回動畫時間- (NSTimeInterval)transitionDuration:(nullable id)transitionContext;//將動畫的代碼寫到里面即可- (void)animateTransition:(id)transitionContext;

首先我自定義一個名為LRTransitionPushController的類繼承于NSObject準守了UIViewControllerAnimatedTransitioning協議

 - (void)animateTransition:(id)transitionContext{   self.transitionContext = transitionContext;   //獲取源控制器 注意不要寫成 UITransitionContextFromViewKey LRTransitionPushController *fromVc = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; //獲取目標控制器 注意不要寫成 UITransitionContextToViewKey LRTransitionPopController *toVc = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];   //獲得容器視圖 UIView *containView = [transitionContext containerView]; // 都添加到container中。注意順序 目標控制器的view需要后面添加 [containView addSubview:fromVc.view]; [containView addSubview:toVc.view];   UIButton *button = fromVc.button; //繪制圓形 UIBezierPath *startPath = [UIBezierPath bezierPathWithOvalInRect:button.frame];   //創建兩個圓形的 UIBezierPath 實例;一個是 button 的 size ,另外一個則擁有足夠覆蓋屏幕的半徑。最終的動畫則是在這兩個貝塞爾路徑之間進行的 //按鈕中心離屏幕最遠的那個角的點 CGPoint finalPoint; //判斷觸發點在那個象限 if(button.frame.origin.x > (toVc.view.bounds.size.width / 2)){  if (button.frame.origin.y < (toVc.view.bounds.size.height / 2)) {   //第一象限   finalPoint = CGPointMake(0, CGRectGetMaxY(toVc.view.frame));  }else{   //第四象限   finalPoint = CGPointMake(0, 0);  } }else{  if (button.frame.origin.y < (toVc.view.bounds.size.height / 2)) {   //第二象限   finalPoint = CGPointMake(CGRectGetMaxX(toVc.view.frame), CGRectGetMaxY(toVc.view.frame));  }else{   //第三象限   finalPoint = CGPointMake(CGRectGetMaxX(toVc.view.frame), 0);  } }  CGPoint startPoint = CGPointMake(button.center.x, button.center.y); //計算向外擴散的半徑 = 按鈕中心離屏幕最遠的那個角距離 - 按鈕半徑 CGFloat radius = sqrt((finalPoint.x-startPoint.x) * (finalPoint.x-startPoint.x) + (finalPoint.y-startPoint.y) * (finalPoint.y-startPoint.y)) - sqrt(button.frame.size.width/2 * button.frame.size.width/2 + button.frame.size.height/2 * button.frame.size.height/2); UIBezierPath *endPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(button.frame, -radius, -radius)];   //賦值給toVc視圖layer的mask CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.path = endPath.CGPath; toVc.view.layer.mask = maskLayer;   CABasicAnimation *maskAnimation =[CABasicAnimation animationWithKeyPath:@"path"]; maskAnimation.fromValue = (__bridge id)startPath.CGPath; maskAnimation.toValue = (__bridge id)endPath.CGPath; maskAnimation.duration = [self transitionDuration:transitionContext]; maskAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; maskAnimation.delegate = self; [maskLayer addAnimation:maskAnimation forKey:@"path"]; }

在控制器里面用來自定義轉場動畫的方法里返回剛才自定義的動畫類

- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{   if (operation == UINavigationControllerOperationPush) {  return [LRTranstionAnimationPush new]; }else{  return nil; }}

到此為止自定義轉場動畫就完成了

pop的動畫只是把push動畫反過來做一遍這里就不細講了,有疑問的可以去看代碼

添加滑動返回手勢

上面說到這個方法是為這個動畫添加用戶交互的所以我們要在pop時實現滑動返回

最簡單的方式應該就是利用UIKit提供的UIPercentDrivenInteractiveTransition類了,這個類已經實現了UIViewControllerInteractiveTransitioning協議,同學men可以通過這個類的對象指定轉場動畫的完成百分比。

//為這個動畫添加用戶交互- (nullable id)navigationController:(UINavigationController *)navigationController       interactionControllerForAnimationController:(id) animationController NS_AVAILABLE_IOS(7_0);

第一步 添加手勢

 UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [self.view addGestureRecognizer:gestureRecognizer];

第二步 通過用戶滑動的變化確定動畫執行的比例

- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer {   /*調用UIPercentDrivenInteractiveTransition的updateInteractiveTransition:方法可以控制轉場動畫進行到哪了,  當用戶的下拉手勢完成時,調用finishInteractiveTransition或者cancelInteractiveTransition,UIKit會自動執行剩下的一半動畫,  或者讓動畫回到最開始的狀態。*/    if ([gestureRecognizer translationInView:self.view].x>=0) {  //手勢滑動的比例  CGFloat per = [gestureRecognizer translationInView:self.view].x / (self.view.bounds.size.width);  per = MIN(1.0,(MAX(0.0, per)));     if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {       self.interactiveTransition = [UIPercentDrivenInteractiveTransition new];   [self.navigationController popViewControllerAnimated:YES];      } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){       if([gestureRecognizer translationInView:self.view].x ==0){         [self.interactiveTransition updateInteractiveTransition:0.01];        }else{         [self.interactiveTransition updateInteractiveTransition:per];   }      } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateCancelled){       if([gestureRecognizer translationInView:self.view].x == 0){         [self.interactiveTransition cancelInteractiveTransition];    self.interactiveTransition = nil;        }else if (per > 0.5) {         [ self.interactiveTransition finishInteractiveTransition];   }else{         [ self.interactiveTransition cancelInteractiveTransition];   }   self.interactiveTransition = nil;  }      } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){  [self.interactiveTransition updateInteractiveTransition:0.01];  [self.interactiveTransition cancelInteractiveTransition];  } else if ((gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateCancelled)){     self.interactiveTransition = nil; }  }

第三步 在為動畫添加用戶交互的代理方法里返回UIPercentDrivenInteractiveTransition的實例

- (id)navigationController:(UINavigationController *)navigationController       interactionControllerForAnimationController:(id) animationController { return self.interactiveTransition;}

如果感覺這篇文章對您有所幫助,順手點個喜歡,謝謝啦

代碼放在了GitHub上大家可以下載,當然也可以通過本地下載

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内外成人免费激情在线视频网站| 日韩av一卡二卡| 久久久av网站| 国产精品九九九| 国产脚交av在线一区二区| 欧美精品videofree1080p| 欧美成人h版在线观看| 国产亚洲欧洲在线| 日韩电视剧在线观看免费网站| 色婷婷av一区二区三区在线观看| 国产一区二区三区在线看| 日韩欧美国产高清91| 亚洲区中文字幕| 欧美性猛交xxxx乱大交蜜桃| 91在线观看免费高清完整版在线观看| 国产精品第10页| 欧美最猛黑人xxxx黑人猛叫黄| 国产日韩欧美电影在线观看| 亚洲第一精品久久忘忧草社区| 青草成人免费视频| 亚洲最大福利网站| 欧美综合一区第一页| 精品久久久视频| 国产精品啪视频| 日韩欧美在线网址| 欧美日韩在线第一页| 久久久国产精品免费| 欧美另类69精品久久久久9999| 97av视频在线| 精品久久久久久久久久ntr影视| 成人福利网站在线观看11| 久久国产精品影视| 日韩免费av一区二区| 日本精品久久中文字幕佐佐木| 欧美最猛黑人xxxx黑人猛叫黄| 亚洲乱码一区av黑人高潮| 久久久久久久一区二区| 国产精品三级久久久久久电影| 欧美日韩精品中文字幕| 亚洲欧洲午夜一线一品| 亚洲成人精品av| 亚洲精品大尺度| 欧美视频在线看| 欧美日韩国产成人高清视频| 黄色成人在线免费| 欧美在线中文字幕| 日韩高清a**址| 成人av电影天堂| 日韩av在线免费观看一区| 日韩中文字幕在线观看| 久久好看免费视频| 精品国偷自产在线视频| 国产成人精品一区| 日本中文字幕不卡免费| 亚洲欧美成人在线| 亚洲男人天堂古典| 91麻豆桃色免费看| 欧美丰满片xxx777| 日韩视频免费观看| 亚洲精品自拍第一页| 欧美激情精品久久久久久大尺度| 亚洲丝袜在线视频| 91chinesevideo永久地址| 亚洲国产一区自拍| 欧美成人免费视频| 久色乳综合思思在线视频| 日韩在线免费观看视频| 宅男66日本亚洲欧美视频| 国产视频亚洲精品| 成人福利网站在线观看11| 国产精品丝袜一区二区三区| 555www成人网| 国产精品极品美女粉嫩高清在线| 亚洲欧美中文日韩在线| 亚洲小视频在线| 国产精品视频在线观看| 午夜精品一区二区三区在线视频| 一区二区三区在线播放欧美| 午夜精品久久久久久99热软件| 在线观看国产精品日韩av| 亚洲成人免费网站| 欧美成人精品在线| 亚洲三级免费看| 久久免费精品视频| 欧美日韩国产一区二区三区| 欧美日韩国产精品专区| 97在线看免费观看视频在线观看| 欧美体内谢she精2性欧美| 亚洲午夜色婷婷在线| 九九精品视频在线观看| 日韩h在线观看| 久久影视电视剧凤归四时歌| 日韩暖暖在线视频| x99av成人免费| 国产日韩在线观看av| 亚洲一区二区免费| 欧美网站在线观看| 中文国产成人精品久久一| 中文字幕亚洲字幕| 欧美超级免费视 在线| 亚洲成成品网站| 亚洲日韩中文字幕在线播放| 久久久亚洲影院你懂的| 国产精品久久二区| 久久久99免费视频| 国产精品入口夜色视频大尺度| 欧美性少妇18aaaa视频| 亚洲欧美国产一本综合首页| 国产不卡精品视男人的天堂| 亚洲精品国产拍免费91在线| 欧美性xxxxx极品娇小| 国产成人av在线播放| 国产午夜精品一区理论片飘花| 欧美日韩aaaa| 97在线观看视频| 性欧美长视频免费观看不卡| 成人h猎奇视频网站| 亚洲xxxx妇黄裸体| 最近2019免费中文字幕视频三| 亚洲成人精品av| 亚洲欧洲日产国码av系列天堂| 久久综合久久美利坚合众国| 国a精品视频大全| 91中文字幕一区| 欧美精品日韩www.p站| 亚洲一区二区免费在线| 亚洲护士老师的毛茸茸最新章节| 欧美色播在线播放| 伊人久久男人天堂| 久久视频精品在线| 国产精品av在线播放| 日韩欧美成人网| 日韩精品免费在线播放| 久久久久久久久电影| 欧美极品美女电影一区| 最新国产精品亚洲| 亚洲图片欧洲图片av| 欧美国产日韩中文字幕在线| 国产精品黄页免费高清在线观看| 最新的欧美黄色| 26uuu国产精品视频| 国产亚洲精品美女久久久久| 亚洲午夜小视频| 91精品在线观看视频| 久久久久久高潮国产精品视| 国产乱人伦真实精品视频| 亚洲人成电影网站色| 81精品国产乱码久久久久久| 美女精品久久久| 亚洲第一av网| 亚洲乱码一区二区| 最新国产成人av网站网址麻豆| 久久亚洲春色中文字幕| 国产精品久久久久久av| 国产偷亚洲偷欧美偷精品| 国产精品日韩在线播放| 国产成人精品在线观看| 色与欲影视天天看综合网| 亚洲男人天堂视频| 亚洲成人国产精品| 国产精品久久久久久久久久99| 成人深夜直播免费观看| 色综合伊人色综合网| 久久乐国产精品|