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

  • 做一个�类似新浪微博式样的发布界面动画
  • 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 !
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

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