iOS_20_微博自己定义可动画切换的导航控制器
生活随笔
收集整理的這篇文章主要介紹了
iOS_20_微博自己定义可动画切换的导航控制器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
終于效果:
AnimatedNavigationController.h
// // AnimatedNavigationController.h // 20_帥哥no微博 // // Created by beyond on 14-8-10. // Copyright (c) 2014年 com.beyond. All rights reserved. // 繼承自導航控制器,可是多了一個功能,能夠監聽手勢,進行動畫切換#import <UIKit/UIKit.h>@interface AnimatedNavigationController : UINavigationController@end AnimatedNavigationController.m// // AnimatedNavigationController.m // 20_帥哥no微博 // // Created by beyond on 14-8-10. // Copyright (c) 2014年 com.beyond. All rights reserved. //#import "AnimatedNavigationController.h" // 截圖用到 #import <QuartzCore/QuartzCore.h> #import "BeyondViewController.h" @interface AnimatedNavigationController () {// 屏幕截圖UIImageView *_screenshotImgView;// 截圖上面的黑色半透明遮罩UIView *_coverView;// 存放全部截圖NSMutableArray *_screenshotImgs; }@end@implementation AnimatedNavigationController- (void)viewDidLoad {[super viewDidLoad];// 1,創建Pan手勢識別器,并綁定監聽方法UIPanGestureRecognizer *panGestureRec = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRec:)];// 為導航控制器的view加入Pan手勢識別器[self.view addGestureRecognizer:panGestureRec];// 2.創建截圖的ImageView_screenshotImgView = [[UIImageView alloc] init];// app的frame是除去了狀態欄高度的frame_screenshotImgView.frame = [UIScreen mainScreen].applicationFrame;//(0 20; 320 460);// 3.創建截圖上面的黑色半透明遮罩_coverView = [[UIView alloc] init];// 遮罩的frame就是截圖的frame_coverView.frame = _screenshotImgView.frame;// 遮罩為黑色_coverView.backgroundColor = [UIColor blackColor];// 4.存放全部的截圖數組初始化_screenshotImgs = [NSMutableArray array];}// 重寫push方法,在push之前 先截取圖片 - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {// 僅僅有在導航控制器里面有子控制器的時候才須要截圖if (self.viewControllers.count >= 1) {// 調用自己定義方法,使用上下文截圖[self screenShot];}// 截圖完畢之后,才調用父類的push方法[super pushViewController:viewController animated:YES]; }// 使用上下文截圖,并使用指定的區域裁剪,模板代碼 - (void)screenShot {// 將要被截圖的view,即窗體的根控制器的view(必須不含狀態欄,默認ios7中控制器是包括了狀態欄的)BeyondViewController *beyondVC = (BeyondViewController *)self.view.window.rootViewController;// 背景圖片 總的大小CGSize size = beyondVC.view.frame.size;// 開啟上下文,使用參數之后,截出來的是原圖(YES 0.0 質量高)UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);// 要裁剪的矩形范圍CGRect rect = CGRectMake(0, -20.8, size.width, size.height + 20 );//注:iOS7以后renderInContext:由drawViewHierarchyInRect:afterScreenUpdates:替代[beyondVC.view drawViewHierarchyInRect:rect afterScreenUpdates:NO];// 從上下文中,取出UIImageUIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();// 加入截取好的圖片到圖片數組[_screenshotImgs addObject:snapshot];// 千萬記得,結束上下文(移除棧頂的基于當前位圖的圖形上下文)UIGraphicsEndImageContext();}// 監聽手勢的方法,僅僅要是有手勢就會運行 - (void)panGestureRec:(UIPanGestureRecognizer *)panGestureRec {// 假設當前顯示的控制器已經是根控制器了,不須要做不論什么切換動畫,直接返回if(self.topViewController == self.viewControllers[0]) return;// 推斷pan手勢的各個階段switch (panGestureRec.state) {case UIGestureRecognizerStateBegan:// 開始拖拽階段[self dragBegin];break;case UIGestureRecognizerStateEnded:// 結束拖拽階段[self dragEnd];break;default:// 正在拖拽階段[self dragging:panGestureRec];break;} }#pragma mark 開始拖動,加入圖片和遮罩 - (void)dragBegin {// 重點,每次開始Pan手勢時,都要加入截圖imageview 和 遮蓋cover到window中[self.view.window insertSubview:_screenshotImgView atIndex:0];[self.view.window insertSubview:_coverView aboveSubview:_screenshotImgView];// 而且,讓imgView顯示截圖數組中的最后(最新)一張截圖_screenshotImgView.image = [_screenshotImgs lastObject]; }// 默認的將要進行縮放的截圖的初始比例 #define kDefaultScale 0.6 // 默認的將要變透明的遮罩的初始透明度(全黑) #define kDefaultAlpha 1.0// 當拖動的距離,占了屏幕的總寬度的3/4時, 就讓imageview全然顯示。遮蓋全然消失 #define kTargetTranslateScale 0.75 #pragma mark 正在拖動,動畫效果的精髓,進行縮放和透明度變化 - (void)dragging:(UIPanGestureRecognizer *)pan {// 得到手指拖動的位移CGFloat offsetX = [pan translationInView:self.view].x;// 僅僅同意往右邊拖,禁止向左拖if (offsetX < 0) offsetX = 0;// 讓整個導航的view都平移 self.view.transform = CGAffineTransformMakeTranslation(offsetX, 0);// 計算眼下手指拖動位移占屏幕總的寬度的比例,當這個比例達到3/4時, 就讓imageview全然顯示。遮蓋全然消失double currentTranslateScaleX = offsetX/self.view.frame.size.width;// 讓imageview縮放,默認的比例+(當前平移比例/目標平移比例)*(1-默認的比例)double scale = kDefaultScale + (currentTranslateScaleX/kTargetTranslateScale) * (1 - kDefaultScale);// 已經達到原始大小了,就能夠了,不用放得更大了if (scale > 1) scale = 1;_screenshotImgView.transform = CGAffineTransformMakeScale(scale, scale);// 讓遮蓋透明度改變,直到減為0,讓遮罩全然透明,默認的比例-(當前平移比例/目標平移比例)*默認的比例double alpha = kDefaultAlpha - (currentTranslateScaleX/kTargetTranslateScale) * kDefaultAlpha;_coverView.alpha = alpha; }#pragma mark 結束拖動,推斷結束時拖動的距離作對應的處理,并將圖片和遮罩從父控件上移除 - (void)dragEnd {// 取出挪動的距離CGFloat translateX = self.view.transform.tx;// 取出寬度CGFloat width = self.view.frame.size.width;if (translateX <= width * 0.5) {// 假設手指移動的距離還不到屏幕的一半,往左邊挪 (彈回)[UIView animateWithDuration:0.3 animations:^{// 重要~~讓被右移的view彈回歸位,僅僅要清空transform就可以辦到self.view.transform = CGAffineTransformIdentity;// 讓imageView大小恢復默認的scale_screenshotImgView.transform = CGAffineTransformMakeScale(kDefaultScale, kDefaultScale);// 讓遮蓋的透明度恢復默認的alpha 1.0_coverView.alpha = kDefaultAlpha;} completion:^(BOOL finished) {// 重要,動畫完畢之后,每次都要記得 移除兩個view,下次開始拖動時,再加入進來[_screenshotImgView removeFromSuperview];[_coverView removeFromSuperview];}];} else {// 假設手指移動的距離還超過了屏幕的一半,往右邊挪[UIView animateWithDuration:0.3 animations:^{// 讓被右移的view全然挪到屏幕的最右邊,結束之后,還要記得清空view的transformself.view.transform = CGAffineTransformMakeTranslation(width, 0);// 讓imageView縮放置為1_screenshotImgView.transform = CGAffineTransformMakeScale(1, 1);// 讓遮蓋alpha變為0,變得全然透明_coverView.alpha = 0;} completion:^(BOOL finished) {// 重要~~讓被右移的view全然挪到屏幕的最右邊,結束之后,還要記得清空view的transform,不然下次再次開始drag時會出問題,由于view的transform沒有歸零self.view.transform = CGAffineTransformIdentity;// 移除兩個view,下次開始拖動時,再加回來[_screenshotImgView removeFromSuperview];[_coverView removeFromSuperview];// 運行正常的Pop操作:移除棧頂控制器,讓真正的前一個控制器成為導航控制器的棧頂控制器[self popViewControllerAnimated:NO];// 重要~記得這時候,能夠移除截圖數組里面最后一張無用的截圖了[_screenshotImgs removeLastObject];}];} } @end
轉載于:https://www.cnblogs.com/jzssuanfa/p/6844507.html
總結
以上是生活随笔為你收集整理的iOS_20_微博自己定义可动画切换的导航控制器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: day1 of python
- 下一篇: 定时任务 Crontab命令 详解