iOS_20_微博自訂可動畫切換的導航控制器

來源:互聯網
上載者:User

iOS_20_微博自訂可動畫切換的導航控制器

最終效果:





AnimatedNavigationController.h

////  AnimatedNavigationController.h//  20_帥哥no微博////  Created by beyond on 14-8-10.//  Copyright (c) 2014年 com.beyond. All rights reserved.//  繼承自導航控制器,但是多了一個功能,可以監聽手勢,進行動畫切換#import @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 #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];    // 從上下文中,取出UIImage    UIImage *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都平移     // 挪動整個導航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的transform            self.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





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.