iOS自定義交互式轉場動畫-仿微信圖片轉場、酷狗轉場 (從零到一 + 交互式圖片瀏覽器)

轉場動畫

轉場動畫就是從一個場景以動畫的形式過渡到另一個場景。自定義轉場動畫的意義是脫離系統固定的轉場,實現UI交互設計師設計的視覺效果強的轉場動畫。

下圖是整個案例的Demo菜單截圖,為了方便大家一步一步掌握自定義轉場動畫,每個效果我都寫了非常詳細的Demo(包括導航push的轉場和模態modal的轉場),建議大家先下載下來跟著文章一個案例一個案例自己去實現一下,會對理解十分有幫助。github地址:https://github.com/yangli-dev/LYCustomTransition

homemenu.png
效果展示.gif
圖片瀏覽器.gif

目錄

0、CATransition(系統轉場動畫)
一、基礎轉場-非交互式(初步認識自定義轉場動畫)
二、仿酷狗轉場-非交互式(鞏固對轉場的認識)
三、仿微信轉場-非交互式(加強對轉場的認識)
四、基礎轉場-交互式
五、實戰 - 網友提問 - Question One
六、圖片瀏覽器-PictureBrowse

說明:本文章目前只講解了demo中的部分案例,但其它的跟這幾個類似,擴展一下就好,如有問題請留言

0、CATransition(系統轉場動畫)

首先來個最簡單的改變轉場效果的方法(不是自定義,是通過官方提供的動畫效果實現),提供動畫效果的這個類就是CATransition

CATransition

CATransition 是CAAnimation的子類,用于頁面之間的過度動畫,官方提供了四個公有的API動畫效果,但是私有API的效果更加炫酷(謹慎使用私有的API)

(1)Nav導航轉場:要改變轉場動畫,其實方法只有一個,非常容易理解:
[self.navigationController.view.layer addAnimation:[self pushAnimation] forKey:nil]
(2)modal模態轉場:和nav類似,
[self.view.window.layer addAnimation:[self presentAnimation] forKey:nil];
意思是在視圖的圖層上添加一個CAAnimation類動畫,然后圖層執行這個類提供的動畫效果,故轉場動畫也就改變了。
通過CAAnimation 的子類CATransition可以快速創建動畫效果,以下代碼是改變系統轉場動畫的具體實現

- (void)pushSecond{

    LYCATransitionSecondVC *second = [[LYCATransitionSecondVC alloc] init];
    [self.navigationController.view.layer addAnimation:[self pushAnimation] forKey:nil];//添加Animation
    [self.navigationController pushViewController:second animated:NO];  //記得這里的animated要設為NO,不然會重復

/*  modal模態
    LYModalCATransitionSecondVC *second = [[LYModalCATransitionSecondVC alloc] init];
    [self.view.window.layer addAnimation:[self presentAnimation] forKey:nil];//添加Animation
    [self presentViewController:second animated:NO completion:nil];  //記得這里的animated要設為NO,不然會重復
*/
}

- (CATransition *)pushAnimation{
    CATransition* transition = [CATransition animation];
    transition.duration = 0.8;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
    
    /*私有API
     cube                   立方體效果
     pageCurl               向上翻一頁
     pageUnCurl             向下翻一頁
     rippleEffect           水滴波動效果
     suckEffect             變成小布塊飛走的感覺
     oglFlip                上下翻轉
     cameraIrisHollowClose  相機鏡頭關閉效果
     cameraIrisHollowOpen   相機鏡頭打開效果
     */
    transition.type = @"cube";
    //transition.type = kCATransitionMoveIn;
    //下面四個是系統公有的API
    //kCATransitionMoveIn, kCATransitionPush, kCATransitionReveal, kCATransitionFade
    
    transition.subtype = kCATransitionFromRight;
    //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
    
    return transition;
}

看完是不是很簡單,趕緊自己嘗試一下吧。接下來就是真正的自定義轉場動畫的學習了。

真正的自定義轉場從這里開始

從iOS7開始,蘋果提供了真正能自定義轉場動畫的API,這才使得我們可以為APP定義自己特有的轉場效果。轉場有非交互式和交互式轉場,這里當然是從基本的非交互式的轉場開始說起。

其實導航push和模態modal自定義轉場的實現,只是一個協議的區別,
實現push的類去遵循UINavigationControllerDelegate協議;
實現modal的類去遵循UIViewControllerTransitioningDelegate協議。
兩個協議里面的方法都大同小異,所以此系列文章就講push轉場中的案例實現
具體看Demo就知道了_(可能在這里你并不知道這兩個協議是干嘛的,不要擔心,下面馬上就一一道來)

一、基礎轉場-非交互式(初步認識自定義轉場動畫)

完成這個案例只需要簡單的兩步就可實現,耐心并仔細看下去,你會發現自定義轉場其實也很簡單!

1. 遵循UINavigationControllerDelegate協議,設置代理。

比如在Demo中的Nav-BaseTransition案例,在LYNavBaseVC本個類中自己遵循UINavigationControllerDelegate此協議,在push轉場之前設置代理self.navigationController.delegate = self,然后再實現其協議特有方法,當push操作執行時,就會回調實現的代理方法,代理方法會要求返回遵循了UIViewControllerAnimatedTransitioning協議的代理對象,從而去執行所對應的動畫。(代碼中的LYNavBaseCustomAnimator是遵循了UIViewControllerAnimatedTransitioning協議的類,這個協議是專門在轉場中提供并執行轉場動畫,稍后會在第2小節詳細介紹)

- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC;

具體代碼實現

- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                            animationControllerForOperation:(UINavigationControllerOperation)operation
                                                         fromViewController:(UIViewController *)fromVC
                                                           toViewController:(UIViewController *)toVC{
    if (operation == UINavigationControllerOperationPush) {
        return self.customAnimator;
        
    }else if (operation == UINavigationControllerOperationPop){
        return self.customAnimator;
    }
    return nil;
}

- (LYNavBaseCustomAnimator *)customAnimator
{
    if (_customAnimator == nil) {
        _customAnimator = [[LYNavBaseCustomAnimator alloc]init];
    }
    return _customAnimator;
}
2.創建提供動畫效果的執行者

上述代碼中的LYNavBaseCustomAnimator就是動畫效果的執行者。它是遵循了UIViewControllerAnimatedTransitioning協議的類。

協議 UIViewControllerAnimatedTransitioning,這個協議是轉場動畫中,動畫效果的執行者,實現這個協議的類具有負責給轉場提供各種復雜動畫效果的能力。協議里有兩個必須要實現的方法

//這個方法控制轉場動畫的時間長度
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
//這個是轉場上下文,提供轉場過程中兩個控制器的具體信息。
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;`

具體代碼實現

- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
    return 0.5;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
    //轉場過渡的容器view
    UIView *containerView = [transitionContext containerView];
    
    //FromVC
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = fromViewController.view;
    fromView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    
    //ToVC
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toViewController.view;
    toView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    
    //此處判斷是push,還是pop 操作
    BOOL isPush = ([toViewController.navigationController.viewControllers indexOfObject:toViewController] > [fromViewController.navigationController.viewControllers indexOfObject:fromViewController]);
    
    if (isPush) {
        [containerView addSubview:fromView];
        [containerView addSubview:toView];//push,這里的toView 相當于secondVC的view
        toView.frame = CGRectMake(kScreenWidth, kScreenHeight, kScreenWidth, kScreenHeight);
    
    }else{
        [containerView addSubview:toView];
        [containerView addSubview:fromView];//pop,這里的fromView 也是相當于secondVC的view
        fromView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    }
    //因為secondVC的view在firstVC的view之上,所以要后添加到containerView中
    
    //動畫
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        if (isPush) {
            toView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
        }else{
            fromView.frame = CGRectMake(kScreenWidth, kScreenHeight, kScreenWidth, kScreenHeight);
        }
    } completion:^(BOOL finished) {
        BOOL wasCancelled = [transitionContext transitionWasCancelled];
        //設置transitionContext通知系統動畫執行完畢
        [transitionContext completeTransition:!wasCancelled];
    }];
}

這里簡單介紹下fromView和toView,不然大家可能會有點繞

A          push --->     B
B           pop --->     A
||                      ||
fromView              toView 

誰在轉場中主動發起轉場,誰就是fromVC、fromView
A主動push到B,A就是fromVC
B主動pop到A,B就是fromVC

從代碼中可以看出,轉場動畫的自定義,就是對fromView和toView的操作,而這兩個view都是可以在這個協議的上下文中獲取,所以,
我們不難實現一些簡單的自定義轉場。

案例一小結

對于非交互式的轉場來說,其實就只需要實現兩個協議的相關方法:
第一個是UINavigationControllerDelegate,作用好比是告訴系統我有自己的轉場動畫了,我要去調我自定義的。
第二個是UIViewControllerAnimatedTransitioning,作用好比是我制作好了動畫了,需要的你直接調用就好了。

二、仿酷狗轉場-非交互式(鞏固對轉場的認識)

動畫解析:

首先可以了解到這個動畫其實也是一個線性動畫,只不過是弧線形的,那么給定起始和終止狀態的位置就可以了。跟案例一類似,只不過這里多了一個旋轉,這個動畫可以用組動畫CAAnimationGroup實現,但是鑒于效果不是太流暢,這里我采用的是仿射變換CGAffineTransform實現的。代碼如下

@implementation LYNavKuGouPushAnimator

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

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    //轉場過渡的容器view
    UIView *containerView = [transitionContext containerView];
    
    //ToVC
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toViewController.view;
    [containerView addSubview:toView];
    
    //動畫 仿射變換動畫
    float centerX = toView.bounds.size.width * 0.5;
    float centerY = toView.bounds.size.height * 0.5;
    float x = toView.bounds.size.width * 0.5;
    float y = toView.bounds.size.height * 1.8;
    
    //起始狀態: 原始狀態繞x,y旋轉45o后的狀態
    CGAffineTransform trans = [self GetCGAffineTransformRotateAroundCenterX:centerX centerY:centerY x:x y:y angle:45.0/180.0*M_PI];
    toView.transform = trans;
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        
        //終止狀態: 原始狀態
        toView.transform = CGAffineTransformIdentity;
        
    } completion:^(BOOL finished) {
        
        BOOL wasCancelled = [transitionContext transitionWasCancelled];
                
        //設置transitionContext通知系統動畫執行完畢
        [transitionContext completeTransition:!wasCancelled];
    }];
}

/**
 仿射變換
 
 @param centerX     view的中心點X坐標
 @param centerY     view的中心點Y坐標
 @param x           旋轉中心x坐標
 @param y           旋轉中心y坐標
 @param angle       旋轉的角度
 @return            CGAffineTransform對象
 */
- (CGAffineTransform)GetCGAffineTransformRotateAroundCenterX:(float)centerX centerY:(float)centerY x:(float)x y:(float)y angle:(float)angle{
    
    CGFloat l = y - centerY;
    CGFloat h = l * sin(angle);
    CGFloat b = l * cos(angle);
    CGFloat a = l - b;
    CGFloat x1 = h;
    CGFloat y1 = a;
    
    CGAffineTransform  trans = CGAffineTransformMakeTranslation(x1, y1);
    trans = CGAffineTransformRotate(trans,angle);
    
    return trans;
}
@end

看到這個類的代碼是不是更清爽了,那是因為從這個案例開始起我就把push和pop的Animator分別用一個類實現(LYNavKuGouPushAnimatorLYNavKuGouPopAnimator),這樣大家理解起來思路也會更清晰啦~
(還有從這個案例開始UINavigationControllerDelegate協議也用一個單獨的類實現,比如這個案例中的LYNavKuGouAnimationTransition就是遵循并實現了該協議方法的類,在控制器中設置這個類的對象為代理即可)

案例二小結

該轉場動畫的精髓也就是
GetCGAffineTransformRotateAroundCenterX: centerY: x: y: angle:方法,這個方法使得可以根據傳入的參數計算出view的變換后的位置狀態。(關于CGAffineTransform更多知識,請自行Google,這里就不贅述了)
有了變換前后的狀態,動畫效果用一個簡單的UIView動畫也就可以實現了。

三、仿微信轉場-非交互式(加強對轉場的認識)

動畫分析:首先看下示例圖

微信轉場示例.png

這個動畫和前兩個動畫就有點不同了,前兩個動畫是對整個界面進行的動畫操作,而這個動畫只是對縮放的圖片進行動畫操作,背景顏色僅做了漸變效果。
既然知道了只是對圖片進行動畫操作,那就不難想到,在containerView上加上一個UIImageView,然后對此做動畫操作,即可完成需求。
看下代碼:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    //轉場過渡的容器view
    UIView *containerView = [transitionContext containerView];
    
    //FromVC
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIView *fromView = fromViewController.view;
    [containerView addSubview:fromView];
    
    //ToVC
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *toView = toViewController.view;
    [containerView addSubview:toView];
    toView.hidden = YES;
    
    //圖片背景的空白view (設置和控制器的背景顏色一樣,給人一種圖片被調走的假象 [可以換種顏色看看效果])
    UIView *imgBgWhiteView = [[UIView alloc] initWithFrame:self.transitionBeforeImgFrame];
    imgBgWhiteView.backgroundColor = bgColor;
    [containerView addSubview:imgBgWhiteView];
    
    //有漸變的黑色背景
    UIView *bgView = [[UIView alloc] initWithFrame:containerView.bounds];
    bgView.backgroundColor = [UIColor blackColor];
    bgView.alpha = 0;
    [containerView addSubview:bgView];
    
    //過渡的圖片
    UIImageView *transitionImgView = [[UIImageView alloc] initWithImage:self.transitionImgView.image];
    transitionImgView.frame = self.transitionBeforeImgFrame;
    [transitionContext.containerView addSubview:transitionImgView];
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.3 options:UIViewAnimationOptionCurveLinear animations:^{
        
        transitionImgView.frame = self.transitionAfterImgFrame;
        bgView.alpha = 1;
        
    } completion:^(BOOL finished) {
        
        toView.hidden = NO;
        
        [imgBgWhiteView removeFromSuperview];
        [bgView removeFromSuperview];
        [transitionImgView removeFromSuperview];
        
        BOOL wasCancelled = [transitionContext transitionWasCancelled];
        //設置transitionContext通知系統動畫執行完畢
        [transitionContext completeTransition:!wasCancelled];
    }];
    
}

代碼中,空白view和漸變的黑色背景都是扮演輔助角色的,而過渡圖片才是核心。要實現動畫效果,必須得有三個數據:image圖像、轉場前imageView的frame和轉場后imageView的frame。這三個數據都是從第一個VC里面計算得來的,只需按邏輯步驟一步步傳過來即可。
其中要注意的點:
(1) toView加到containerView上時,需要先隱藏,等到動畫結束時再顯示,不然toView 會蓋住整個fromView。
(2) 其中除了系統的fromView和toView,其它所有的view在動畫結束時必須移除,不然會一直在containerView上存在。
(3) popAnimator 中的fromView 不用加到containerView中了,因為此轉場在pop時不需要fromView的參與了,加上會出現整個界面沒有變化的bug。

案例三小結:

1.在VC中計算好Animator中必要的三個參數,然后依次傳遞到Animator中。
2.獲取得到傳入的數據,對過渡圖片根據做動畫處理

四、基礎轉場-交互式

交互式轉場:人為控制轉場過渡,最常見的交互轉場動畫就是系統自帶的側滑返回。

此案例請對照demo

1.實現代理方法

LYNavBaseInteractiveAnimatedTransition類里,相較于案例一中的UINavigationControllerDelegate協議,要多實現一個代理方法, 即:

- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                                   interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController;

此方法會返回一個遵循了UIViewControllerInteractiveTransitioning協議的代理對象,實現這個方法,系統轉場時,就會知道當前是否有交互式的轉場,有便執行交互轉場,無則執行普通自定義的轉場動畫。
具體代碼實現:

- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                            animationControllerForOperation:(UINavigationControllerOperation)operation
                                                         fromViewController:(UIViewController *)fromVC
                                                           toViewController:(UIViewController *)toVC{
    if (operation == UINavigationControllerOperationPush) {
        return self.customAnimator;
        
    }else if (operation == UINavigationControllerOperationPop){
        return self.customAnimator;
    }
    return nil;
}

- (LYNavBaseCustomAnimator *)customAnimator
{
    if (_customAnimator == nil) {
        _customAnimator = [[LYNavBaseCustomAnimator alloc]init];
    }
    return _customAnimator;
}

- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                                   interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController{
    
    if (self.gestureRecognizer)
        return self.percentIntractive;
    else
        return nil;
}

- (void)setGestureRecognizer:(UIPanGestureRecognizer *)gestureRecognizer{
    _gestureRecognizer = gestureRecognizer;
}
- (LYNavBasePercentDerivenInteractive *)percentIntractive{
    if (!_percentIntractive) {
        _percentIntractive = [[LYNavBasePercentDerivenInteractive alloc] initWithGestureRecognizer:self.gestureRecognizer];
    }
    return _percentIntractive;
}

其中,
(1)gestureRecognizer 是在secondVC加入的一個交互手勢,在pop時是需要傳遞過來的,后面會講到。
(2)percentIntractive 是LYNavBasePercentDerivenInteractive 類對象,這個類繼承于 UIPercentDrivenInteractiveTransition類,UIPercentDrivenInteractiveTransition類是交互轉場中的核心類,后面會講到。

2.新建一個繼承于 UIPercentDrivenInteractiveTransition類的類 LYNavBasePercentDerivenInteractive

UIPercentDrivenInteractiveTransition類是系統定義的,它遵循了 UIViewControllerInteractiveTransitioning協議,故可做為第一節中的代理對象。
此類又定義了三個方法供交互轉場時調用:

//更新轉場過程的百分比
- (void)updateInteractiveTransition:(CGFloat)percentComplete;
//取消轉場
- (void)cancelInteractiveTransition;
//完成轉場
- (void)finishInteractiveTransition;

具體代碼實現:

- (void)gestureRecognizeDidUpdate:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGFloat scale = 1 - [self percentForGesture:gestureRecognizer];
    
    switch (gestureRecognizer.state)
    {
        case UIGestureRecognizerStateBegan:
            //沒用
            
            break;
        case UIGestureRecognizerStateChanged:
            
            //更新百分比
            [self updateInteractiveTransition:scale];
            
            break;
        case UIGestureRecognizerStateEnded:
            
            if (scale < 0.3){
                //取消轉場
                [self cancelInteractiveTransition];
            }
            else{
                //完成轉場
                [self finishInteractiveTransition];
            }
            break;
        default:
            //取消轉場
            [self cancelInteractiveTransition];
            break;
    }
}

在此類中,根據pop時傳遞過來的手勢信息,計算獲得滑動距離所占屏幕的百分比,從而根據百分比來處理轉場的取消與完成。

3.傳值

此處傳值跟之前都有不同的地方,我們這里的交互是在pop時做交互動畫,故傳值是在SecondVC中傳入的。
具體代碼:

- (void)interactiveTransitionRecognizerAction:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
    
    CGFloat scale = 1 - fabs(translation.x / kScreenWidth);
    scale = scale < 0 ? 0 : scale;
    
    NSLog(@"second = %f", scale);
    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStatePossible:
            break;
        case UIGestureRecognizerStateBegan:{
            
            //1. 設置代理
            self.animatedTransition = nil;
            self.navigationController.delegate = self.animatedTransition;
            
            //2. 傳值
            self.animatedTransition.gestureRecognizer = gestureRecognizer;
            
            //3. push跳轉
            [self.navigationController popViewControllerAnimated:YES];
        }
            break;
        case UIGestureRecognizerStateChanged: {
            
            break;
        }
        case UIGestureRecognizerStateFailed:
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded: {
            
            self.animatedTransition.gestureRecognizer = nil;
        }
    }
}

此案例注意的點:
(1)LYNavBaseInteractiveAnimatedTransition類中的customAnimator是直接用的案例一中的

五、實戰 - 網友提問 - Question One

此案例為本文章2樓網友的提問解答

此案例其實和案例三的實現方式基本一致,單從轉場角度來說,不同點可以有兩個:(1)轉場前ImageView的frame不定,案例三中ImageView的frame就一個(2)轉場后的位置跟案例三不同
而這兩個不同點都是我們可以計算得到的,所以要實現這個動畫不難。
先看代碼

// 獲取指定視圖在window中的位置
- (CGRect)getFrameInWindow:(UIView *)view
{
    return [view.superview convertRect:view.frame toView:nil];
}

此方法即可解決(1)中的問題,點擊cell時,傳入cell上的UIImageView對象,即可返回此View在window上的frame,這樣在轉場中的過渡ImageView就可根據此frame設置轉場前的位置了

- (CGRect)backScreenImageViewRectWithImage:(UIImage *)image{
    
    CGSize size = image.size;
    CGSize newSize;
    newSize.height = kScreenWidth * 0.6;
    newSize.width = newSize.height / size.height * size.width;
    
    CGFloat imageY = 0;
    CGFloat imageX = (kScreenWidth - newSize.width) * 0.5;

    CGRect rect =  CGRectMake(imageX, imageY, newSize.width, newSize.height);
    
    return rect;
}

此方法可解決(2)中的問題,傳入image,即可根據自己的需求,計算得出轉場后圖片的位置。

六、圖片瀏覽器-PictureBrowse

封裝了圖片瀏覽器,demo中是封裝的模態方式跳轉,如有需求導航方式push的,請將LYPictureBrowseInteractiveAnimatedTransition類中遵循的協議修改為UINavigationControllerDelegate,并修改相應的代理方法(請仿照上面幾個案例),別忘了跳轉中的present、dismiss修改為push、pop方法。

使用方法:
(1)在你的工程中導入LYPictureBrowse 文件夾,并引入LYPictureBrowse.h 頭文件
(2)構造四個必須的參數transitionImage、firstVCImgFrames、transitionImgIndex、dataSouceArray。具體構造方法請對照demo編寫

-------------------- 完結 --------------------

更新日志:

2017.07.05
(1) 更新案例0 - CATransition
(2) 更新案例一 - 基礎轉場-非交互
(3) 新增案例二 - 仿酷狗轉場-非交互
(4) 新增案例三 - 仿微信轉場-非交互
(5) 新增案例四 - 基礎轉場-交互式
(6) 新增案例五 - 實戰 - 網友提問 - Question One

更新日志:

2017.12.11
(1)新增圖片瀏覽器框架

如果看了本篇文章能對你有所幫助的小伙伴們,就來個贊給個鼓勵吧!畢竟碼字不易 O(∩_∩)O哈哈~

github:https://github.com/yangli-dev/LYCustomTransition

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容