昨天和大家分享了一下xib上的一些细节上的使用技巧,今天和大家分享以下本人第一次做出的比较好看的一个动画,到现在仍觉得这种效果很流行,且好看,是利用layer.mask属性所制作的,废话不多说,先效果图.

  

android 遮罩镂空视图_转场动画

  又看见咱们可爱的夏娜酱~,这是简单的遮罩转场动画,iOS7开始,苹果就已经推出了自定义转场的的API,可以使用CoreAnimation实现转场动画,更加可以出现在两个VC之间任意切换,真正实现了高度解耦,真的是想怎么来就怎么来,只要你能够有创意就行了.下面为大家介绍一下这个简单`的转场动画是怎么做的.

  1.首先在storyBoard上的布局是这样的

  

android 遮罩镂空视图_代理方法_02

 

  放大后可以看到push按钮和pop按钮,使navigationller.navigationBar透明

  2.接着为红色夏娜的`VC绑定ViewController,第二个黑发夏娜VC绑定一个SecondViewController;

  3.为两个VC签订协议<

UINavigationControllerDelegate

>  

  实例如下:

@interfaceUIViewController<UINavigationControllerDelegate>

@propertyweak, nonatomic) IBOutletUIButton *button;

@end

 

@interfaceUIViewController<UINavigationControllerDelegate>

@propertyweak, nonatomic) IBOutletUIButton *button;

 

@end

  我们来先讲push效果是如何做的

  4.重写ViewController的ViewWillAppear的方法,制定navigationController的代理人是自己

  

- (void)viewWillAppear:(BOOL)animated

{

self.navigationController.delegateself;

}

 

  5.实现代理方法

 

#pragma mark --UINavigationControllerDelegate

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationControllerUINavigationControllerOperation)operation fromViewController:(UIViewControllerUIViewController *)toVC

{

ifUINavigationControllerOperationPush) {

        

OvalTransitionOvalTransitionnew];

return ovalTransi;

else{

returnnil;

    }

}

这个代理方法需要返回一个签了UIViewControllerAnimatedTransitioning协议的对象,而我返回的是自定义的OvralTransition对象

  我们来看这一个对象的.h文件下的代码

  

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

@interfaceNSObject<UIViewControllerAnimatedTransitioning>

@end

  6.现在为这一个类签订UIViewControllerAnimatedTransitioning协议.

  7.该类的实现如下

//  Created by 叶杨 on 16/3/15.

//  Copyright © 2016年叶景天. All rights reserved.

//

 

#import "OvalTransition.h"

#import "ViewController.h"

#import "SecondViewController.h"

 

 

@interfaceOvalTransition ()

 

//在类的延展里头添加一个签了转场动画代理方法的上下文对象,方便之后的传值

@propertynonatomic, strong)id<UIViewControllerContextTransitioning>transitionContext;

 

@end

 

 

@implementation OvalTransition

 

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext

{

return 0.7;

}

 

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext

{

//赋值给属性,动画结束时方便传值

self.transitionContext = transitionContext;

    

//获取前一个VC

ViewControllerViewControllerviewControllerForKey:UITransitionContextFromViewControllerKey];

    

//获取后一个VC

SecondViewControllerSecondViewControllerviewControllerForKey:UITransitionContextToViewControllerKey];

    

//获取转场时生成的转场视图view

UIViewcontainerView];

    

UIButtonbutton;

    

UIBezierPathUIBezierPathbezierPathWithOvalInRect:button.frame];

addSubview:fromVC.view];

addSubview:toVC.view];

    

//创建两个圆形的UIBezierPath实例: 一个是button的size,另外一个则拥有足够覆盖屏幕的半径.最终的动画是在这两个圆周路径之中进行的

    

//这里的finalPoint是相对于fromVC.button.center的位置,并不是在屏幕上的位置

CGPoint finalPoint;

    

//判断触发在哪一个象限,当然我们这里很明显是在第一象限,但是这里为了代码的可复用性,我们也必须判断再计算

ifframe.origin.xview.bounds.size.width / 2)) {

ifframe.origin.yview.bounds.size.width / 2)) {

//第一象限

CGPointMake(button.center.xcenter.yCGRectGetMaxY(toVC.view.bounds) + 30);

else{            //第四象限

CGPointMake(button.center.xcenter.y - 0);

            

        }

else{

ifframe.origin.yview.bounds.size.height / 2)) {

//第二象限

CGPointMake(button.center.xCGRectGetMaxX(toVC.view.bounds), button.center.yCGRectGetMaxY(toVC.view.bounds)+30);

else{

//第三象限

CGPointMake(button.center.xCGRectGetMaxX(toVC.view.bounds), button.center.y - 0);

        }

    }

//CGRectInset是返回一个中心点一样但是宽高不一样的矩形

CGFloatsqrt((finalPoint.xx) + (finalPoint.yy));

    

    

UIBezierPathUIBezierPathbezierPathWithOvalInRect:CGRectInset(button.frame, -radius, -radius)];

    

//创建一个来负责展示圆形遮盖

CAShapeLayerCAShapeLayerlayer];

pathCGPath; //将它的指定为最终的来避免在动画完成后会回弹

    

//这里说明一下mask的属性,mask的属性很简单,例如:view上加了一层imageView,如果imageView.layer.mask = layerA,那么layerA上不透明的部分将会被绘制成透明,透明的部分将会把imageView.layer绘制成白色

    

view.layer.mask = maskLayer;

 

    

CABasicAnimationCABasicAnimationanimationWithKeyPath:@"path"];

fromValue__bridgeid)(maskStartBP.CGPath);

toValue__bridgeid)((maskFinalBP.CGPath));

durationselftransitionDuration:transitionContext];

timingFunctionCAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut];

delegateself;

    

addAnimation:maskLayerAnimation forKey:@"path"];

    

    

    

    

    

}

 

#pragma mark - CABasicAnimation的Delegate

 

- (void)animationDidStop:(CAAnimationBOOL)flag{

    

//告诉这个完成

self.transitionContextcompleteTransition:![self. transitionContexttransitionWasCancelled]];

//清除的这里一定要清除,否则会影响响应者链

self.transitionContextviewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.masknil;

self.transitionContextviewControllerForKey:UITransitionContextToViewControllerKey].view.layer.masknil;

}

@end

 

  //最终push完成的效果就是这样的

  

android 遮罩镂空视图_#import_03

  这样就完成了一个简单的遮罩push效果,至于pop的话大家可以根据前面的例子自己做,具体Demo在可以在我的gitHub上下载,下载地址https://github.com/bnb173yjx/maskAnimationDemo  因为storyBoard上没有做适配,所以打开的时候以6plus模拟器打开