一.pop和Core Animation的区别

  1.Core Animation的动画只能添加到layer上

  2.pop的动画能添加到任何对象

  3.pop的底层并非基于Core Animation,是基于CADisplayLink

  4.Core Animation的动画仅仅是表象,并不会真正修改对象的frame/Size等值

  5.pop的动画实时修改对象的属性,真正的修改了对象的属性

二.简单结构

三.pop框架简单使用 -- pop不仅可以给layer添加动画,只要是UIView都可以添加动画

  1.给view添加动画

  2.给layer添加动画

四.项目中的动画效果实现

  1.利用pop框架做动画的时候,如果动画关系到了尺寸或者frame,刚开始控件的尺寸或者frame建议不要设置.有时候会出现问题,如下图.由于pop框架做动画是直接修改的属性,所以可以考虑在fromValue中设置尺寸.

  2.点击取消按钮的动画,实现思路--直接遍历了控制器中子控件,通过xib添加的控件最早,所以做动画的控件从第2个开始遍历

  3.监听按钮的点击 -- 要求是动画依次做完,最后处理对应的事件.

  难点:pop框架提供了动画完成的block,自己的目标就是在动画完成后执行相应的事件处理.例如:点击了'发段子'按钮,先做动画,动画完成,跳转到发段子的控制器.

  解决方案:抽取方法,将点击取消按钮的动画封装起来,并用block作为参数.点击取消按钮,不需要处理事件,那么block就为nil;如果点击'发段子'之类的按钮,将需要处理的代码用block封装.

  

 - (void)cancleWithBlock:(void(^)())btnClickBlock
{
// 点击了取消之后,动画的过程中就不要处理事件了
self.view.userInteractionEnabled = NO; for (int i = ; i < self.view.subviews.count; i++) { UIView *subView = self.view.subviews[i];
POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; anim.toValue = [NSValue valueWithCGPoint:CGPointMake(subView.centerX, subView.centerY + ChaosScreenH)];
anim.beginTime = CACurrentMediaTime() + (i - ) * ChaosTimeInterval;
anim.duration = 0.25; [subView pop_addAnimation:anim forKey:nil];
// 监听最后一个view动画的完成
if (i == self.view.subviews.count - ) {
[anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) { [self dismissViewControllerAnimated:NO completion:nil];
// 判断点击按钮后要执行的block是否为空
if (btnClickBlock) {
btnClickBlock();
}
}];
}
}
} - (IBAction)cancelClick {
[self cancleWithBlock:nil];
} - (void)buttonClick:(UIButton *)button
{
[self cancleWithBlock:^{
if (button.tag == ) {
ChaosLog(@"发视频");
} else if (button.tag == ){
ChaosLog(@"发图片");
} else if (button.tag == ){
ChaosLog(@"发段子");
} else if (button.tag == ){
ChaosLog(@"发声音");
}
}];
}

五.最后是项目中的代码

  

 #import "ChaosPublishViewController.h"
#import "ChaosVerticalButton.h" #import <POP.h> @interface ChaosPublishViewController () @end
@implementation ChaosPublishViewController static CGFloat const ChaosTimeInterval = 0.1;
static CGFloat const ChaosAnimSpeed = ; - (void)viewDidLoad {
[super viewDidLoad]; // 先让所有不能处理事件
self.view.userInteractionEnabled = NO;
// 数据
NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"];
NSArray *titles = @[@"发视频", @"发图片", @"发段子", @"发声音", @"审帖", @"离线下载"]; // 设置按钮位置
CGFloat buttonW = ;
CGFloat buttonH = buttonW + ;
CGFloat startY = (ChaosScreenH - * buttonH) * 0.5;
CGFloat startX = ;
NSInteger maxCols = ; // 列数
CGFloat buttonMargin = (ChaosScreenW - * startX - maxCols * buttonW) / (maxCols - );
// 添加发布类别
for (int i = ; i < images.count; i++) {
ChaosVerticalButton *button = [[ChaosVerticalButton alloc] init];
// button.width = buttonW; // 用了pop后,直接修改了按钮的frame,这里可以先不用设置
// button.height = buttonH; // 设置了动画效果反而不好
[button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
[button setTitle:titles[i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:];
button.tag = i;
// 添加点击事件
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
NSInteger btnRow = i / maxCols; // 按钮所在行
NSInteger btnCol = i % maxCols; // 按钮所在列
CGFloat buttonEndY = startY + btnRow * buttonH; // 按钮最终Y值
CGFloat buttonX = startX + btnCol * (buttonMargin + buttonW); // 按钮X值 [self.view addSubview:button]; // 设置动画
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonEndY - ChaosScreenH, buttonW, buttonH)];
anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonEndY, buttonW, buttonH)];
// anim.springBounciness = 8;
anim.springSpeed = ChaosAnimSpeed;
anim.beginTime = CACurrentMediaTime() + i * ChaosTimeInterval;
[button pop_addAnimation:anim forKey:nil];
} // 添加标语
[self setupSlogan];
} - (void)setupSlogan
{
// 添加标语
UIImageView *sloganImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]];
sloganImageView.y = -;
[self.view addSubview:sloganImageView]; CGFloat centerX = ChaosScreenW * 0.5;
CGFloat centerEndY = ChaosScreenH * 0.2;
CGFloat centerBeginY = centerEndY - ChaosScreenH;
// 设置动画
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerBeginY)];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerEndY)];;
// anim.springBounciness = 8;
anim.springSpeed = ChaosAnimSpeed;
anim.beginTime = CACurrentMediaTime() + * ChaosTimeInterval;
[anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
// 动画完成恢复处理事件的能力
self.view.userInteractionEnabled = YES;
}];
[sloganImageView pop_addAnimation:anim forKey:nil];
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self cancleWithBlock:nil];
} - (void)cancleWithBlock:(void(^)())btnClickBlock
{
// 点击了取消之后,动画的过程中就不要处理事件了
self.view.userInteractionEnabled = NO; for (int i = ; i < self.view.subviews.count; i++) { UIView *subView = self.view.subviews[i];
POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; anim.toValue = [NSValue valueWithCGPoint:CGPointMake(subView.centerX, subView.centerY + ChaosScreenH)];
anim.beginTime = CACurrentMediaTime() + (i - ) * ChaosTimeInterval;
anim.duration = 0.25; [subView pop_addAnimation:anim forKey:nil];
// 监听最后一个view动画的完成
if (i == self.view.subviews.count - ) {
[anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) { [self dismissViewControllerAnimated:NO completion:nil];
// 判断点击按钮后要执行的block是否为空
if (btnClickBlock) {
btnClickBlock();
}
}];
}
}
} - (IBAction)cancelClick {
[self cancleWithBlock:nil];
} - (void)buttonClick:(UIButton *)button
{
[self cancleWithBlock:^{
if (button.tag == ) {
ChaosLog(@"发视频");
} else if (button.tag == ){
ChaosLog(@"发图片");
} else if (button.tag == ){
ChaosLog(@"发段子");
} else if (button.tag == ){
ChaosLog(@"发声音");
}
}];
} @end

iOS不得姐项目--pop框架的初次使用的更多相关文章

  1. iOS不得姐项目--appearance的妙用,再一次设置导航栏返回按钮,导航栏左右按钮的封装(巧用分类)

    一.UI_APPEARANCE_SELECTOR 彩票项目中appearance的用法一直没有搞明白,这次通过第二个项目中老师的讲解,更深一层次的了解到了很多关于appearance的作用以及使用方法 ...

  2. iOS不得姐项目--TabBar的重复点击实现当前模块刷新;状态栏点击实现当前模块回滚到最顶部

    一.实现功能:重复点击tabBar,刷新当前TableView,其余不受影响 <1>实现思路: 错误的方法: TabBar成为自己的代理,监听自己的点击--这种方法是不可取的,如果外面设置 ...

  3. iOS不得姐项目--精华模块上拉下拉的注意事项,日期显示,重构子控制器,计算cell的高度(只计算一次),图片帖子的显示

    一.上拉下拉注意事项 使用MJRefresh中的上拉控件自动设置透明 当请求下页数据通过page的时候,注意的是上拉加载更多数据失败的问题,下拉加载数据失败了,页数应该还原.或者是请求成功的时候再将页 ...

  4. iOS不得姐项目--推荐关注模块(一个控制器控制两个tableView),数据重复请求的问题,分页数据的加载,上拉下拉刷新(MJRefresh)

    一.推荐关注模块(一个控制器控制两个tableView) -- 数据的显示 刚开始加载数据值得注意的有以下几点 导航控制器会自动调整scrollView的contentInset,最好是取消系统的设置 ...

  5. iOS不得姐项目--封装状态栏指示器(UIWindow实现)

    一.头文件 #import <UIKit/UIKit.h> @interface ChaosStatusBarHUD : NSObject /** 显示成功信息 */ + (void)sh ...

  6. iOS不得姐项目--图片帖子模块,大图默认显示最顶部分的处理

    一.刚开始的处理,设置Mode属性(self.pictureImageView.contentMode = UIViewContentModeScaleAspectFill;) 和 Clip Subv ...

  7. iOS不得姐项目--登录模块的布局,设置文本框占位文字颜色,自定义内部控件竖直排列的按钮

    一.登录模块的布局 将一整部分切割成若干部分来完成,如图分成了三部分来完成 设置顶部状态栏为白色的方法 二.设置文本框占位文字颜色 <1>方法一与方法二实现原理是同一种,都是通过设置pla ...

  8. 手把手教你如何搭建iOS项目基本框架

    手把手教你如何搭建iOS项目基本框架 今天我们来谈谈如何搭建框架,框架需要做一些什么. 第一步:找到我们的目标我们的目标是让其他开发人员拿到手后即可写页面,不再需要考虑其他的问题. 第二步:我们需要做 ...

  9. iOS项目——基本框架搭建

    项目开发过程中,在完成iOS项目——项目开发环境搭建之后,我们首先需要考虑的就是我们的项目的整体框架与导航架构设计,然后在这个基础上考虑功能模块的完成. 一 导航架构设计 一款App的导航架构设计应该 ...

随机推荐

  1. hdu-5493 Queue(二分+树状数组)

    题目链接: Queue Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  2. UVA 12169 Disgruntled Judge【扩展欧几里德】

    题意:随机选取x1,a,b,根据公式xi=(a*xi-1+b)%10001得到一个长度为2*n的序列,奇数项作为输入,求偶数项,若有多种,随机输出一组答案. 思路:a和b均未知,可以考虑枚举a和b,时 ...

  3. excel技巧

    1. 使文字自动适配方格大小. 自动调整行高(但是合并后的方格不行)

  4. QFontMetrics的一个问题

    今天发现QFontMetric的一个问题 QFontMetrics可以输入一个字体和一个字符串,计算出字符串在这种字体下的显示尺寸. 这种计算比较耗时间,因此Qt内部应该是缓存了计算结果.具体方法是在 ...

  5. 在Java代码中使用pdfBox将PDF转换为图片

    生成图片 // 生成图片 PDDocument pd = PDDocument.load(new File(filePath)); PDFRenderer pdfRenderer = new PDFR ...

  6. Linux socket多进程服务器框架三

    在使用select管理服务器连接的时候: 注意1:select是可中断睡眠函数,需要屏蔽信号 注意2:必须获取select的返回值nread,每次处理完一个事件,nread需要-1 注意3:如果客户端 ...

  7. &12-2 查找二叉搜索树

    #1,定理 在一棵高度为h的二叉搜索树上,动态集合上的操作SEARCH.MINIMUM.MAXIMUM.SUCCESSOR和PREDECESSOR可以在O(h)时间内完成. #2,伪代码 分别是搜索, ...

  8. 【传递智慧】C++基础班公开课第六期培训

    11月11日 二 213 进程间关系和守护进程 11月12日 三 213 信号 11月13日 四     11月14日 五 213 线程(创建,销毁,回收) 11月15日 六 213 线程同步机制 1 ...

  9. 分析cocos2d-x中的CrystalCraze示例游戏

    cocos2d-x自带了不少示例,以及几个比较简单的游戏,不过这些游戏都是用javascript binding(SpiderMonkey)做的,所以我猜测javascript binding可能是c ...

  10. C语言复习(1)

    test.c #include <stdio.h> int main(){ printf("hello\n"); return 0; } 1.预处理阶段 由于在test ...