自定義畫面切換的效果

追求極致的產(chǎn)品的體驗(yàn)是我們作為開(kāi)發(fā)者的重要目標(biāo)。IOS7以后蘋果更改了不同view之間的切換的方式。如果你是移動(dòng)設(shè)備請(qǐng)點(diǎn)擊獲得更好的閱讀效果。

1. Old in IOS5,IOS6

之前IOS5和IOS6中的一般是采用ChildrenViewController的方式完成過(guò)渡和切換效果,類似的代碼如下:

[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self.view addSubview:toVc.View];

__weak id weakself = self;
[self transitionFromViewController:fromVC 
                  toViewController:toVC duration:0.3 
                           options:UIViewAnimationOptionTransitionCrossDissolve 
                        animations:^{} 
                        completion:^(BOOL finished) { 
    [fromVC removeFromSuperView]; 
    [fromVC removeFromParentViewController]; 
    [toVC didMoveToParentViewController:weakSelf]; 
}];
2. New in IOS7

為了解決代碼高度耦合的問(wèn)題,IOS7提供了一套自定義的VC切換。

先看一下相關(guān)的API,可以查看UIViewControllerTransitioning.h

@protocol UIViewControllerContextTransitioning <NSObject>

這個(gè)接口提供了VC之間切換的上下文,包括兩個(gè)vc切換時(shí)候的舞臺(tái)containerView,取出fromVC和ToVc,結(jié)束轉(zhuǎn)換和取消轉(zhuǎn)換等。這個(gè)一般不需要我們來(lái)實(shí)現(xiàn),在下面的UIViewControllerAnimatedTransitioning中可以取到。

@protocol UIViewControllerAnimatedTransitioning <NSObject>

這個(gè)接口是實(shí)現(xiàn)轉(zhuǎn)換的主要場(chǎng)地。在它的方法中- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;來(lái)實(shí)現(xiàn)我們的動(dòng)畫部分。這個(gè)是我們需要實(shí)現(xiàn)的主要部分。它的另一個(gè)是函數(shù)用來(lái)指定動(dòng)畫的時(shí)間。

@protocol UIViewControllerTransitioningDelegate <NSObject>

這個(gè)是用來(lái)返回你的在呈現(xiàn)VC和解散VC時(shí)候的UIViewControllerAnimatedTransitioning,我們可以做寫一個(gè)TransitionManger用來(lái)管理動(dòng)畫的效果,用工廠的方法來(lái)返回需要的動(dòng)畫效果。把視圖控制的TransitioningDelegate實(shí)現(xiàn)交給他。

3.Demo

前一段時(shí)間,需要做一個(gè)類似AlertViewController的東東,但是需要能支持在view中插入subview。于是就用這個(gè)實(shí)現(xiàn)了一番,其實(shí)很簡(jiǎn)單,先看一下效果:

Simulator Screen Shot Oct 17, 2015, 12.29.14 PM.png

使用TransitioningDelegate的核心就是在container中寫出fromVc和ToVc的轉(zhuǎn)換過(guò)程。Alertview是ToVC而AlertView后面的半通明黑色就是Container的地盤,container的下面是fromVc。明白這些后,我們來(lái)開(kāi)始寫實(shí)現(xiàn)過(guò)程

==寫一個(gè)實(shí)現(xiàn)UIViewControllerAnimatedTransitioning的Animation類

@implementation SMAlertModelAnnimation{
    UIView *_coverView;
    NSArray *_constraints;
}

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 1.0f;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    UIView *containerView  =[transitionContext containerView];
    
    //The modal view itself
    UIView *modalView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
    
    //View to darken the area behind the modal view
    if (!_coverView) {
        _coverView = [[UIView alloc] initWithFrame:containerView.frame];
        _coverView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6];
        _coverView.alpha = 0.0;
    } else _coverView.frame = containerView.frame;
    [containerView addSubview:_coverView];
    
    [containerView addSubview:modalView];
    
    //Move off of the screen so we can slide it up
    CGRect endFrame = modalView.frame;
    modalView.frame = CGRectMake(endFrame.origin.x, containerView.frame.size.height, endFrame.size.width, endFrame.size.height);
    [containerView bringSubviewToFront:modalView];
    
    //Animate using spring animation
    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.8 initialSpringVelocity:1.0 options:0 animations:^{
        modalView.frame = endFrame;
        _coverView.alpha = 0.6f;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];
    }];

}

這里取消了添加約束的代碼,為的是讓你更加明白這段代碼的核心地方。 第一個(gè)方法返回了動(dòng)畫的時(shí)間,第二個(gè)方法分成了大概的三個(gè)部分

  • 添加一個(gè)converView作為黑色模態(tài)的背景
  • 通過(guò)UITransitionContextToViewControllerKey取出目標(biāo)ToVc的view把它添加到Container的view中,并制定view的初始位置
  • 添加自定義的動(dòng)畫效果

需要注意的是[transitionContext completeTransition:YES];這樣方法是必須要加的來(lái)保證告訴控制器轉(zhuǎn)換完成。

==調(diào)用
新建一個(gè)TransitionManager用來(lái)實(shí)現(xiàn)UIViewControllerTransitionDelegate
我們可以在其中封裝一個(gè)Enumeration類型叫做TransitionStyle
然后在- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source方法中根據(jù)type返回我們的animation類型

先建一個(gè)ToVC的視圖控制器,在init或者initWithCoder中更改他的呈現(xiàn)方式

    self.modalPresentationStyle = UIModalPresentationCustom;
    transitionManager = [SMTransitionManager new];
    transitionManager.presentStyle = SMTransitionStyleAlertModel;
    self.transitioningDelegate = transitionManager;

這樣我們就很快的實(shí)現(xiàn)了這個(gè)VC的轉(zhuǎn)換效果,SMTransitionManager可以重用到任何的VC中。在我的代碼中建了一個(gè)AlertBaseViewController,配好storyboard之后,之間讓storyboard的類繼承AlertBaseViewController,不需要在多寫一行Code就能實(shí)現(xiàn)這種model效果。

明白了他們的工作原理,你就可以寫出各式各樣的動(dòng)畫效果了,跟我們寫一個(gè)View的動(dòng)畫效果將沒(méi)有什么不同。剩下的就是好好研究一下CoreAnimation了吧。

Demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容