前言
說到APP用戶體驗,就離不開動畫。在這篇文章里,簡單實現了點擊一個按鈕彈出多個按鈕的動畫,在此拋磚引玉,供大家參考。
思路
首先創建需要被彈出的多個按鈕,然后創建點擊彈出的POP按鈕,將其覆蓋在多個按鈕之上,最后在POP按鈕點擊事件里邊利用UIView動畫和CABasicAnimation動畫,就可以實現簡單的彈出效果。
按鈕層次結構圖.png
主要代碼
創建UI,這里使用數組來裝多個按鈕,方便后面取用。
@interface ViewController ()
/**彈出按鈕 */
@property (nonatomic,strong) UIButton *popButton;
/**按鈕數組*/
@property (nonatomic,strong) NSMutableArray *buttonArray;
@end
@implementation ViewController
- (UIButton *) popButton
{
if (_popButton == nil)
{
_popButton = [[UIButton alloc]initWithFrame:CGRectMake(self.view.centerX - 30, self.view.centerY - 30 + 180, 60, 60)];
[self.view addSubview:_popButton];
[_popButton addTarget:self action:@selector(popAction:) forControlEvents:UIControlEventTouchUpInside];
}
return _popButton;
}
- (NSMutableArray *) buttonArray
{
if (_buttonArray==nil)
{
_buttonArray=[[NSMutableArray alloc]init];
}
return _buttonArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
//注意順序
[self initUI];
self.popButton.backgroundColor = [UIColor grayColor];
}
- (void)initUI
{
//循環創建按鈕
for (NSInteger i = 0; i<5; i++)
{
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(self.view.centerX - 30,self.view.centerY - 30 + 180, 60, 60)];
//標記tag
button.tag = 100+i;
button.backgroundColor = [UIColor orangeColor];
NSString *string = [NSString stringWithFormat:@"%ld",i];
[button setTitle:string forState:UIControlStateNormal];
button.layer.cornerRadius = 30;
[button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[self.buttonArray addObject:button];
}
}
在POP按鈕點擊事件中,根據按鈕的選中狀態來判斷是彈出還是收回多個按鈕。這里使用的適配,是自己寫的一個UIView的分類,參考代碼適配常用分類
/**
按鈕點擊響應
*/
- (void)popAction:(UIButton *)button
{
if (button.selected == NO)
{
//彈出
[self show];
button.selected = YES;
}
else
{
//消失
[self dismiss];
button.selected = NO;
}
}
彈出多個按鈕。這里需要注意的是,彈出按鈕,只是一個動畫效果,按鈕本身的位置還是沒有改變,需要我們在動畫結束后,重新設置按鈕的位置。
/**
彈出
*/
- (void)show
{
//旋轉彈出按鈕
[UIView animateWithDuration:popTime animations:^{
self.popButton.transform = CGAffineTransformMakeRotation(M_PI_2/2);
}];
//取出按鈕,添加動畫
[self.buttonArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//位移動畫
UIButton *button = self.buttonArray[idx];
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"position"];
anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(_popButton.centerX, _popButton.centerY)];
anima.toValue = [NSValue valueWithCGPoint:CGPointMake(self.view.centerX, self.view.centerY + 80 * idx - 250)];
anima.duration = popTime;
anima.fillMode = kCAFillModeForwards;
anima.removedOnCompletion = NO;
anima.beginTime = CACurrentMediaTime() + 0.02 * idx;
[button.layer addAnimation:anima forKey:nil];
//縮放動畫
CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnima.duration = popTime;
scaleAnima.fromValue = @0;
scaleAnima.toValue = @1;
scaleAnima.fillMode = kCAFillModeForwards ;
scaleAnima.removedOnCompletion = NO ;
scaleAnima.beginTime = CACurrentMediaTime() + 0.02 * idx;
[button.layer addAnimation:scaleAnima forKey:nil];
//等動畫結束后,改變按鈕真正位置
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(popTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
button.center = CGPointMake(self.view.centerX, self.view.centerY + 80 * idx - 250);
});
}];
}
隱藏彈出的多個按鈕
/**
隱藏
*/
- (void)dismiss
{
[UIView animateWithDuration:popTime animations:^{
self.popButton.transform = CGAffineTransformMakeRotation(0);
}];
[self.buttonArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIButton *button = self.buttonArray[idx];
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"position"];
anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.view.centerX, self.view.centerY + 80 * idx - 250)];
anima.toValue = [NSValue valueWithCGPoint:CGPointMake(_popButton.centerX, _popButton.centerY)];
anima.duration = popTime;
anima.fillMode = kCAFillModeForwards;
anima.removedOnCompletion = NO;
anima.beginTime = CACurrentMediaTime() + 0.02 * (4 - idx);
[button.layer addAnimation:anima forKey:nil];
CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnima.duration = popTime;
scaleAnima.fromValue = @1;
scaleAnima.toValue = @0;
scaleAnima.fillMode = kCAFillModeForwards ;
scaleAnima.removedOnCompletion = NO ;
scaleAnima.beginTime = CACurrentMediaTime() + 0.02 * (4 - idx);
[button.layer addAnimation:scaleAnima forKey:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(popTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
button.center = CGPointMake(_popButton.centerX, _popButton.centerY);
});
}];
}
效果圖
效果圖.gif