一个发布界面动画效果的实现

字数 2402阅读 6557
  • 做一个�类似新浪微博式样的发布界面动画
  • githubi地址:PublishAnimation
  • 可以看得出来这个动画虽然是一点一点执行的,但是你一点击加号按钮,就立马有个蒙版盖在上面
    • 要实现这个有三种方案:
      • 1.拿到这个TabBarController的View,然后addSubViews,加一个View上去
      • 2.拿到Window,然后addSubViews,加一个View上去
      • 3.直接modal出来(只是在印象中,modal出来是有一个默认的动画的,但是我们只要传参数animated的时候给一个NO的参数,就没有动画效果了)
  • 既然这样我们还是选择modal出来。而且这个动画里面的逻辑有点多,所以我们给它一个控制器去管理算了
  • 先创建CYPublishViewController,并勾选Xib
    • 有一点得注意:Xib的宽高是(600,600),并不是我们最终要显示的宽高
    • 我们的View是(375 ,600),他们是有差别的,要注意细节

  • ViewDidLoad:方法是View刚刚加载完,你的View是从Xib加载的,从Xib刚刚加载完的View它的宽高是和我们屏幕显示出来的View不一样的
  • 所以从Xib描述控制器的View的时候,你千万要小心这个问题,你在那里拿到的控制器的View的宽高有时候不是最终的
    • 但是Storybard里面加载是不会这样的事情发生的,因为它会自动调整好子控件的位置,这是Storybard较Xib先进的地方
  • 但是控制器也提供了这么一个方法,专门去布局控制器里面View的子控件,叫做ViewDidLayoutSubviews方法中
  • 这里有一种开发的模式:
    • 你可以在ViewDidLoad:方法先添加,然后在ViewDidLayoutSubviews方法中再布局--这种开发模式也必须保证控制器里面有属性
    • 但是我们要做动画还是不在这里做了

  • 有一种添加\布局子控件的方法
    • 1.在viewDidLoad方法中创建、添加子控件
    • 2.在viewDidLayoutSubviews方法中布局子控件

  • 在Xib中布局好imageView背景图片以及取消按钮
  • 从CYTabBar的publishClick:方法中modal出发布界面的控制器
    • �拿到窗口的根控制器,才能在这里modal出来
- (void)publishClick
{
    CYPublishViewController *publish = [[CYPublishViewController alloc] init];
    [self.window.rootViewController presentViewController:publish animated:NO completion:nil];
}

  • 对应里面的动画,我们肯定用代码去实现,而不用Xib,因为Xib里面的东西是固定死的,里面往下掉的按钮,写个for循环就搞定了
  • 对于动态的东西,我们还是用代码实现


  • 而且对于做这种动画的效果,我们先不要考虑动画,先将画面里面的东西固定好,这样都能做出来了,那么我们只要调整它们一开始的位置在屏幕外面就可以了

  • 屏幕尺寸的宽和高会经常用到,所以写入到PCH文件中
// 屏幕尺寸
#define CYScreenH [UIScreen mainScreen].bounds.size.height
#define CYScreenW [UIScreen mainScreen].bounds.size.width

  • 由图片我们分析:
    • 先设置上面的标语
/** 标语 */
@property (nonatomic, weak) UIImageView *sloganView;

- (void)setupSloganView
{
    CGFloat sloganY = CYScreenH * 0.2;

    // 添加
    UIImageView *sloganView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
    sloganView.y = sloganY - CYScreenH;
    sloganView.centerX = CYScreenW * 0.5;
    [self.view addSubview:sloganView];
    self.sloganView = sloganView;
  • 六个按钮的设置
  • 我们为了简单起见,如果产品经理没有什么特殊要求的话,我们就让按钮的尺寸为屏幕宽度的三分之一,这样就不用去考虑间距问题了。它们就黏在一起了,这就好算了
  • 首先在CYPublishViewController.m文件中,设置按钮的排布(九宫格排布)
- (void)setupButtons
{
    // 数据
    NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"];
    NSArray *titles = @[@"发视频", @"发图片", @"发段子", @"发声音", @"审帖", @"离线下载"];

    // 一些参数
    NSUInteger count = images.count;
    int maxColsCount = 3; // 一行的列数
    NSUInteger rowsCount = (count + maxColsCount - 1) / maxColsCount;

    // 按钮尺寸
    CGFloat buttonW = CYScreenW / maxColsCount;
    CGFloat buttonH = buttonW * 0.85;
    CGFloat buttonStartY = (CYScreenH - rowsCount * buttonH) * 0.5;
    for (int i = 0; i < count; i++) {
        // 创建、添加
        CYPublishButton *button = [CYPublishButton buttonWithType:UIButtonTypeCustom];
        button.width = -1; // 按钮的尺寸为0,还是能看见文字缩成一个点,设置按钮的尺寸为负数,那么就看不见文字了
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.buttons addObject:button];
        [self.view addSubview:button];

        // 内容
        [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
        [button setTitle:titles[i] forState:UIControlStateNormal];

        // frame
        CGFloat buttonX = (i % maxColsCount) * buttonW;
        CGFloat buttonY = buttonStartY + (i / maxColsCount) * buttonH;
}
  • 你会发现设置后为这个样子:
  • 所以我们要调整按钮里面的图片和文字,因此我们自定义按钮CYPublishButton
  • 在CYPublishButton.m文件中布局好图片和文字的位置
#import "CYPublishButton.h"

@implementation CYPublishButton

    // 初始化
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        self.titleLabel.font = [UIFont systemFontOfSize:15];
        [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.imageView.y = 0;
    self.imageView.centerX = self.width * 0.5;

    self.titleLabel.width = self.width;
    self.titleLabel.y = CGRectGetMaxY(self.imageView.frame);
    self.titleLabel.x = 0;
    self.titleLabel.height = self.height - self.titleLabel.y;
}

@end

  • 接下来就是动画的实现
    • 我们从图片中可以看出来这个动画里面的东西,是从上面往下面掉,按钮,一个个往下掉完后,标语再往下掉,而且有点弹簧效果
    • 其实这里也就是设置好它们Y值的位置就行了
  • 这里做这种弹簧式的动画有三种方法:
    • 1.让它们比如说按钮,从屏幕外先掉到一个下面的位置,然后再往上移一个位置,只是这里要给两个动画,这个方法比较笨
    • 2.用苹果自带的方法,也可以做弹簧效果


    • 3.用facebook出品的动画框架--pop,这个在一些公司里面也在用
      • 这里我们对比与苹果系统自带的核心动画
  • 苹果自带的核心动画,它是作用对象是在图层上面的


  • 苹果自带的核心动画,它是无法监听到动画的中间值
    • 比如说:X ==10-->X == 100.你是无法监听到中间的增长值的:你是无法知道动画的第0.5秒,第0.8秒,第1秒的时候它的值是多少的。也就是说X从10增长到100这个过程中,它的中间值你是拿不到的
    • 苹果自带的核心动画你只要把开始和结束的值传给它就行,中间的值它会给你算好,而且开始和结束他们值的增长和修改只是一个假象,你并不能拿到中间值
  • pop动画可以作用在任何对象上,而且可以监听到动画的中间值
    • 比如说:你可以让一个Money对象做动画,往1-->2-->3-->4-->5-->6-->7-->8。你能控制它弹回8-->7-->6-->5.也就是监听到中间值
  • pop的实现机制也不一样,它里面用了一个CADisplayLink的东西,自己内部搞了一套定时器,而且里面有许多的C++代码
  • 这里pop动画是让它作用在View上,而不是Layer上

    • 基本动画


    • 弹簧动画


  • 这里还有一个poppingLearnCube-iOS它不是框架,它是一个示例程序,它是教你怎么使用pop也是值得大家学习的,里面有许多好的动画效果,工作中是可以用得着的。你可以学习它是怎么写的,github上搜索Animation也会搜索出许多好的动画的框架或者是示例程序像:JHChainableAnimations

  • �还有awesome-ios-animation收集整理了下iOS平台下比较主流炫酷的�许多动画框架。反正对我们今后要做动画都有参考价值

 1.pop
 1> facebook出品的动画框架
 2> 动画能作用在任何对象上
 3> 能监听到动画的中间值

 2.Core Animation
 1> 苹果官方的动画框架
 2> 动画只能作用在CALayer上
 3> 无法监听到动画的中间值

  • 下面开始做动画

  • 按钮的动画:


    for (int i = 0; i < count; i++) {
        // 创建、添加
        CYPublishButton *button = [CYPublishButton buttonWithType:UIButtonTypeCustom];
        button.width = -1; // 按钮的尺寸为0,还是能看见文字缩成一个点,设置按钮的尺寸为负数,那么就看不见文字了
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.buttons addObject:button];
        [self.view addSubview:button];

        // 内容
        [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
        [button setTitle:titles[i] forState:UIControlStateNormal];

        // frame
        CGFloat buttonX = (i % maxColsCount) * buttonW;
        CGFloat buttonY = buttonStartY + (i / maxColsCount) * buttonH;

        // 动画
        POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
        //  开始的位置(这里的宽高之所以不设置为0而保持和最终的位置一致,因为传0的话会发现按钮在慢慢变大,而我们需要是一个从上面掉下来的效果
        anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY - CYScreenH, buttonW, buttonH)];
        //  最终的位置
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY, buttonW, buttonH)];
        anim.springSpeed = CYSpringFactor;
        anim.springBounciness = CYSpringFactor;
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
        //  anim.beginTime = CACurrentMediaTime() + 0.1 * i;这里不这么写,是为了可以实现乱序的效果,哪个按钮先往下掉,可以由我们决定
        [button pop_addAnimation:anim forKey:nil];
    }
}
  • anim.beginTime = CACurrentMediaTime() + 0.1 * i;这里不这么写,是为了可以实现乱序的效果,今后哪个按钮先往下掉,可以由我们决定
  • button.width = -1;
    • 尽管按钮的宽度高度为0,但是只要你给按钮设置了文字,所有按钮就挤成了一个点,它还是能显示一点点黑黑的文字的,这是按钮的一个特点,设置按钮的尺寸为负数,那么就看不见文字了,这是一个小细节

    UIImageView *sloganView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
    sloganView.y = sloganY - CYScreenH;
    sloganView.centerX = CYScreenW * 0.5;
    [self.view addSubview:sloganView];
    self.sloganView = sloganView;

    CYWeakSelf;
    // 动画
    POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    anim.toValue = @(sloganY);
    anim.springSpeed = CYSpringFactor;
    anim.springBounciness = CYSpringFactor;
    // CACurrentMediaTime()获得的是当前时间
    anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
  • 这是标语的动画,给它先设置一个开始的Y值,让它在屏幕外开始做动画,因为它是最后出来的

@interface CYPublishViewController ()
/** 标语 */
@property (nonatomic, weak) UIImageView *sloganView;
/** 按钮 */
@property (nonatomic, strong) NSMutableArray *buttons;

/** 动画时间 */
@property (nonatomic, strong) NSArray *times;
@end

@implementation CYPublishViewController

- (NSMutableArray *)buttons
{
    if (!_buttons) {
        _buttons = [NSMutableArray array];
    }
    return _buttons;
}

- (NSArray *)times
{
    if (!_times) {
        CGFloat interval = 0.1; // 时间间隔
        _times = @[@(5 * interval),
                   @(4 * interval),
                   @(3 * interval),
                   @(2 * interval),
                   @(0 * interval),
                   @(1 * interval),
                   @(6 * interval)]; // 标语的动画时间
    }
    return _times;
}
  • 设置时间间隔,按钮的时间间隔以及标语的时间间隔,标语加载时间是用self.times.lastObject doubleValue取数组中最后一个

  • 在CYPublishViewController.m文件中
#import "CYPublishViewController.h"
#import "CYPublishButton.h"
#import "POP.h"

static CGFloat const CYSpringFactor = 10;

@interface CYPublishViewController ()
/** 标语 */
@property (nonatomic, weak) UIImageView *sloganView;
/** 按钮 */
@property (nonatomic, strong) NSMutableArray *buttons;

/** 动画时间 */
@property (nonatomic, strong) NSArray *times;
@end

@implementation CYPublishViewController

- (NSMutableArray *)buttons
{
    if (!_buttons) {
        _buttons = [NSMutableArray array];
    }
    return _buttons;
}

- (NSArray *)times
{
    if (!_times) {
        CGFloat interval = 0.1; // 时间间隔
        _times = @[@(5 * interval),
                   @(4 * interval),
                   @(3 * interval),
                   @(2 * interval),
                   @(0 * interval),
                   @(1 * interval),
                   @(6 * interval)]; // 标语的动画时间
    }
    return _times;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // 禁止交互
    self.view.userInteractionEnabled = NO;

    // 按钮
    [self setupButtons];

    // 标语
    [self setupSloganView];
}

- (void)setupButtons
{
    // 数据
    NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"];
    NSArray *titles = @[@"发视频", @"发图片", @"发段子", @"发声音", @"审帖", @"离线下载"];

    // 一些参数
    NSUInteger count = images.count;
    int maxColsCount = 3; // 一行的列数
    NSUInteger rowsCount = (count + maxColsCount - 1) / maxColsCount;

    // 按钮尺寸
    CGFloat buttonW = CYScreenW / maxColsCount;
    CGFloat buttonH = buttonW * 0.85;
    CGFloat buttonStartY = (CYScreenH - rowsCount * buttonH) * 0.5;
    for (int i = 0; i < count; i++) {
        // 创建、添加
        CYPublishButton *button = [CYPublishButton buttonWithType:UIButtonTypeCustom];
        button.width = -1; // 按钮的尺寸为0,还是能看见文字缩成一个点,设置按钮的尺寸为负数,那么就看不见文字了
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.buttons addObject:button];
        [self.view addSubview:button];

        // 内容
        [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
        [button setTitle:titles[i] forState:UIControlStateNormal];

        // frame
        CGFloat buttonX = (i % maxColsCount) * buttonW;
        CGFloat buttonY = buttonStartY + (i / maxColsCount) * buttonH;

        // 动画
        POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
        //  开始的位置(这里的宽高之所以不设置为0而保持和最终的位置一致,因为传0的话会发现按钮在慢慢变大,而我们需要是一个从上面掉下来的效果
        anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY - CYScreenH, buttonW, buttonH)];
        //  最终的位置
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY, buttonW, buttonH)];
        anim.springSpeed = CYSpringFactor;
        anim.springBounciness = CYSpringFactor;
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
        //  anim.beginTime = CACurrentMediaTime() + 0.1 * i;这里不这么写,是为了可以实现乱序的效果,哪个按钮先往下掉,可以由我们决定
        [button pop_addAnimation:anim forKey:nil];
    }
}

- (void)setupSloganView
{
    CGFloat sloganY = CYScreenH * 0.2;

    // 添加
    UIImageView *sloganView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
    sloganView.y = sloganY - CYScreenH;
    sloganView.centerX = CYScreenW * 0.5;
    [self.view addSubview:sloganView];
    self.sloganView = sloganView;

    CYWeakSelf;
    // 动画
    POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    anim.toValue = @(sloganY);
    anim.springSpeed = CYSpringFactor;
    anim.springBounciness = CYSpringFactor;
    // CACurrentMediaTime()获得的是当前时间
    anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
    [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        // 开始交互
        weakSelf.view.userInteractionEnabled = YES;
    }];
    [sloganView.layer pop_addAnimation:anim forKey:nil];
}

- (void)buttonClick:(CYPublishButton *)button
{
    CYLogFunc;
}


  • 我们首先创建添加很多按钮,一添加按钮的时候设置它的宽度为负数,让它不会显示出黑点,然后设置图片和文字,然后让按钮从一个很上面的位置跑到它最终的位置,然后按钮的时间随着i值的不同,它弹出的先后时间也就不同
  • 按钮弹出完了后,接下里添加标语,标语是让它拿到最后的时间弹出来,最后弹出效果做出来了

  • 接下来是退出时候的动画,让它按照从前的顺序往下掉

  • 给取消按钮拖线

  • 然后给按钮创建一个数组,懒加载

  • 退出的动画用POPBasicAnimation就行了

  • 控制器销毁的时候要监听动画完毕时的状态用[anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {}

  • 有block的敌方最好加上CYWeakSelf;

  • 还有一个细节:两个动画如果一起执行,就会出现混乱,这样是完全不行的,你的控制用户是否能够点击

    • 在viewDidLoad:方法中,一进来,首先要控制View不能点击,只有控制它不能点击了,那么里面的六个按钮和标语都不能点击了。self.view.userInteractionEnabled = NO;
    • 在最后一个View标语动画加载完后,用户可以点击weakSelf.view.userInteractionEnabled = YES;
    • 同样一旦你点击了取消按钮,用户不能点击self.view.userInteractionEnabled = NO;
  • 而且这种效果,在一些应用中,你点击控制器蒙版的时候,这个整一个也会往下掉,所以在CYPublishViewController.m加一个方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self cancel];
}
- (IBAction)cancel {
    // 禁止交互
    self.view.userInteractionEnabled = NO;

    // 让按钮执行动画
    for (int i = 0; i < self.buttons.count; i++) {
        CYPublishButton *button = self.buttons[i];

        POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
        anim.toValue = @(button.layer.position.y + CYScreenH);
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
        [button.layer pop_addAnimation:anim forKey:nil];
    }

    CYWeakSelf;
    // 让标题执行动画
    POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    anim.toValue = @(self.sloganView.layer.position.y + CYScreenH);
    // CACurrentMediaTime()获得的是当前时间
    anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
    [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        [weakSelf dismissViewControllerAnimated:NO completion:nil];
    }];
    [self.sloganView.layer pop_addAnimation:anim forKey:nil];
}


  • 在CYPublishViewController.m文件中
#import "CYPublishViewController.h"
#import "CYPublishButton.h"
#import "POP.h"

static CGFloat const CYSpringFactor = 10;

@interface CYPublishViewController ()
/** 标语 */
@property (nonatomic, weak) UIImageView *sloganView;
/** 按钮 */
@property (nonatomic, strong) NSMutableArray *buttons;

/** 动画时间 */
@property (nonatomic, strong) NSArray *times;
@end

@implementation CYPublishViewController

- (NSMutableArray *)buttons
{
    if (!_buttons) {
        _buttons = [NSMutableArray array];
    }
    return _buttons;
}

- (NSArray *)times
{
    if (!_times) {
        CGFloat interval = 0.1; // 时间间隔
        _times = @[@(5 * interval),
                   @(4 * interval),
                   @(3 * interval),
                   @(2 * interval),
                   @(0 * interval),
                   @(1 * interval),
                   @(6 * interval)]; // 标语的动画时间
    }
    return _times;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // 禁止交互
    self.view.userInteractionEnabled = NO;

    // 按钮
    [self setupButtons];

    // 标语
    [self setupSloganView];
}

- (void)setupButtons
{
    // 数据
    NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"];
    NSArray *titles = @[@"发视频", @"发图片", @"发段子", @"发声音", @"审帖", @"离线下载"];

    // 一些参数
    NSUInteger count = images.count;
    int maxColsCount = 3; // 一行的列数
    NSUInteger rowsCount = (count + maxColsCount - 1) / maxColsCount;

    // 按钮尺寸
    CGFloat buttonW = CYScreenW / maxColsCount;
    CGFloat buttonH = buttonW * 1.2;
    CGFloat buttonStartY = (CYScreenH - rowsCount * buttonH) * 0.5;
    for (int i = 0; i < count; i++) {
        // 创建、添加
        CYPublishButton *button = [CYPublishButton buttonWithType:UIButtonTypeCustom];
        button.width = -1; // 按钮的尺寸为0,还是能看见文字缩成一个点,设置按钮的尺寸为负数,那么就看不见文字了
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.buttons addObject:button];
        [self.view addSubview:button];

        // 内容
        [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
        [button setTitle:titles[i] forState:UIControlStateNormal];

        // frame
        CGFloat buttonX = (i % maxColsCount) * buttonW;
        CGFloat buttonY = buttonStartY + (i / maxColsCount) * buttonH;

        // 动画
        POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
        anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY - CYScreenH, buttonW, buttonH)];
        anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonY, buttonW, buttonH)];
        anim.springSpeed = CYSpringFactor;
        anim.springBounciness = CYSpringFactor;
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
        [button pop_addAnimation:anim forKey:nil];
    }
}

- (void)setupSloganView
{
    CGFloat sloganY = CYScreenH * 0.2;

    // 添加
    UIImageView *sloganView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
    sloganView.y = sloganY - CYScreenH;
    sloganView.centerX = CYScreenW * 0.5;
    [self.view addSubview:sloganView];
    self.sloganView = sloganView;

    CYWeakSelf;
    // 动画
    POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    anim.toValue = @(sloganY);
    anim.springSpeed = CYSpringFactor;
    anim.springBounciness = CYSpringFactor;
    // CACurrentMediaTime()获得的是当前时间
    anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
    [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        // 开始交互
        weakSelf.view.userInteractionEnabled = YES;
    }];
    [sloganView.layer pop_addAnimation:anim forKey:nil];
}

- (void)buttonClick:(CYPublishButton *)button
{
    CYLogFunc;
}

- (IBAction)cancel {
    // 禁止交互
    self.view.userInteractionEnabled = NO;

    // 让按钮执行动画
    for (int i = 0; i < self.buttons.count; i++) {
        CYPublishButton *button = self.buttons[i];

        POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
        anim.toValue = @(button.layer.position.y + CYScreenH);
        // CACurrentMediaTime()获得的是当前时间
        anim.beginTime = CACurrentMediaTime() + [self.times[i] doubleValue];
        [button.layer pop_addAnimation:anim forKey:nil];
    }

    CYWeakSelf;
    // 让标题执行动画
    POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
    anim.toValue = @(self.sloganView.layer.position.y + CYScreenH);
    // CACurrentMediaTime()获得的是当前时间
    anim.beginTime = CACurrentMediaTime() + [self.times.lastObject doubleValue];
    [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
        [weakSelf dismissViewControllerAnimated:NO completion:nil];
    }];
    [self.sloganView.layer pop_addAnimation:anim forKey:nil];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self cancel];
}
@end
  • 最后就实现了



  • 如果觉得对你有帮助,�Give me a star !

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
  • 2017.02.22 可以练习,每当这个时候,脑袋就犯困,我这脑袋真是神奇呀,一说让你做事情,你就犯困,你可不要太...
  • 1.自定义控件 a.继承某个控件 b.重写initWithFrame方法可以设置一些它的属性 c.在layouts...
  • 下午收到移民局的批件和子行邀请函,明天人事帮我去递签,不出意外两周我就滚蛋了。 占星学说过我!9月开始行冥王运,工...
  • 这几天雾霾差点搞得我差点儿抑郁。恰好周末前同事加老板打电话过来,问我如何。倒完了霾的苦水,末了,那头说:哪天霾太重...