一.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封裝.
1 - (void)cancleWithBlock:(void(^)())btnClickBlock 2 { 3 // 點擊了取消之后,動畫的過程中就不要處理事件了 4 self.view.userInteractionEnabled = NO; 5 6 for (int i = 2; i < self.view.subviews.count; i++) { 7 8 UIView *subView = self.view.subviews[i]; 9 POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; 10 11 anim.toValue = [NSValue valueWithCGPoint:CGPointMake(subView.centerX, subView.centerY + ChaosScreenH)]; 12 anim.beginTime = CACurrentMediaTime() + (i - 2) * ChaosTimeInterval; 13 anim.duration = 0.25; 14 15 [subView pop_addAnimation:anim forKey:nil]; 16 // 監聽最后一個view動畫的完成 17 if (i == self.view.subviews.count - 1) { 18 [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) { 19 20 [self dismissViewControllerAnimated:NO completion:nil]; 21 // 判斷點擊按鈕后要執行的block是否為空 22 if (btnClickBlock) { 23 btnClickBlock(); 24 } 25 }]; 26 } 27 } 28 } 29 30 - (IBAction)cancelClick { 31 [self cancleWithBlock:nil]; 32 } 33 34 - (void)buttonClick:(UIButton *)button 35 { 36 [self cancleWithBlock:^{ 37 if (button.tag == 0) { 38 ChaosLog(@"發視頻"); 39 } else if (button.tag == 1){ 40 ChaosLog(@"發圖片"); 41 } else if (button.tag == 2){ 42 ChaosLog(@"發段子"); 43 } else if (button.tag == 3){ 44 ChaosLog(@"發聲音"); 45 } 46 }]; 47 }
五.最后是項目中的代碼

1 #import "ChaosPublishViewController.h" 2 #import "ChaosVerticalButton.h" 3 4 #import <POP.h> 5 6 @interface ChaosPublishViewController () 7 8 @end 9 @implementation ChaosPublishViewController 10 11 static CGFloat const ChaosTimeInterval = 0.1; 12 static CGFloat const ChaosAnimSpeed = 15; 13 14 - (void)viewDidLoad { 15 [super viewDidLoad]; 16 17 // 先讓所有不能處理事件 18 self.view.userInteractionEnabled = NO; 19 // 數據 20 NSArray *images = @[@"publish-video", @"publish-picture", @"publish-text", @"publish-audio", @"publish-review", @"publish-offline"]; 21 NSArray *titles = @[@"發視頻", @"發圖片", @"發段子", @"發聲音", @"審帖", @"離線下載"]; 22 23 // 設置按鈕位置 24 CGFloat buttonW = 72; 25 CGFloat buttonH = buttonW + 30; 26 CGFloat startY = (ChaosScreenH - 2 * buttonH) * 0.5; 27 CGFloat startX = 30; 28 NSInteger maxCols = 3; // 列數 29 CGFloat buttonMargin = (ChaosScreenW - 2 * startX - maxCols * buttonW) / (maxCols - 1); 30 // 添加發布類別 31 for (int i = 0; i < images.count; i++) { 32 ChaosVerticalButton *button = [[ChaosVerticalButton alloc] init]; 33 // button.width = buttonW; // 用了pop后,直接修改了按鈕的frame,這里可以先不用設置 34 // button.height = buttonH; // 設置了動畫效果反而不好 35 [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal]; 36 [button setTitle:titles[i] forState:UIControlStateNormal]; 37 [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 38 button.titleLabel.font = [UIFont systemFontOfSize:14]; 39 button.tag = i; 40 // 添加點擊事件 41 [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside]; 42 NSInteger btnRow = i / maxCols; // 按鈕所在行 43 NSInteger btnCol = i % maxCols; // 按鈕所在列 44 CGFloat buttonEndY = startY + btnRow * buttonH; // 按鈕最終Y值 45 CGFloat buttonX = startX + btnCol * (buttonMargin + buttonW); // 按鈕X值 46 47 [self.view addSubview:button]; 48 49 // 設置動畫 50 POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame]; 51 anim.fromValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonEndY - ChaosScreenH, buttonW, buttonH)]; 52 anim.toValue = [NSValue valueWithCGRect:CGRectMake(buttonX, buttonEndY, buttonW, buttonH)]; 53 // anim.springBounciness = 8; 54 anim.springSpeed = ChaosAnimSpeed; 55 anim.beginTime = CACurrentMediaTime() + i * ChaosTimeInterval; 56 [button pop_addAnimation:anim forKey:nil]; 57 } 58 59 // 添加標語 60 [self setupSlogan]; 61 } 62 63 - (void)setupSlogan 64 { 65 // 添加標語 66 UIImageView *sloganImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"app_slogan"]]; 67 sloganImageView.y = -200; 68 [self.view addSubview:sloganImageView]; 69 70 CGFloat centerX = ChaosScreenW * 0.5; 71 CGFloat centerEndY = ChaosScreenH * 0.2; 72 CGFloat centerBeginY = centerEndY - ChaosScreenH; 73 // 設置動畫 74 POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter]; 75 anim.fromValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerBeginY)]; 76 anim.toValue = [NSValue valueWithCGPoint:CGPointMake(centerX, centerEndY)];; 77 // anim.springBounciness = 8; 78 anim.springSpeed = ChaosAnimSpeed; 79 anim.beginTime = CACurrentMediaTime() + 6 * ChaosTimeInterval; 80 [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) { 81 // 動畫完成恢復處理事件的能力 82 self.view.userInteractionEnabled = YES; 83 }]; 84 [sloganImageView pop_addAnimation:anim forKey:nil]; 85 } 86 87 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 88 { 89 [self cancleWithBlock:nil]; 90 } 91 92 - (void)cancleWithBlock:(void(^)())btnClickBlock 93 { 94 // 點擊了取消之后,動畫的過程中就不要處理事件了 95 self.view.userInteractionEnabled = NO; 96 97 for (int i = 2; i < self.view.subviews.count; i++) { 98 99 UIView *subView = self.view.subviews[i]; 100 POPBasicAnimation *anim = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter]; 101 102 anim.toValue = [NSValue valueWithCGPoint:CGPointMake(subView.centerX, subView.centerY + ChaosScreenH)]; 103 anim.beginTime = CACurrentMediaTime() + (i - 2) * ChaosTimeInterval; 104 anim.duration = 0.25; 105 106 [subView pop_addAnimation:anim forKey:nil]; 107 // 監聽最后一個view動畫的完成 108 if (i == self.view.subviews.count - 1) { 109 [anim setCompletionBlock:^(POPAnimation *anim, BOOL finished) { 110 111 [self dismissViewControllerAnimated:NO completion:nil]; 112 // 判斷點擊按鈕后要執行的block是否為空 113 if (btnClickBlock) { 114 btnClickBlock(); 115 } 116 }]; 117 } 118 } 119 } 120 121 - (IBAction)cancelClick { 122 [self cancleWithBlock:nil]; 123 } 124 125 - (void)buttonClick:(UIButton *)button 126 { 127 [self cancleWithBlock:^{ 128 if (button.tag == 0) { 129 ChaosLog(@"發視頻"); 130 } else if (button.tag == 1){ 131 ChaosLog(@"發圖片"); 132 } else if (button.tag == 2){ 133 ChaosLog(@"發段子"); 134 } else if (button.tag == 3){ 135 ChaosLog(@"發聲音"); 136 } 137 }]; 138 } 139 140 @end