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