btn_AnimationShow(按钮 简易弹出收复动画)

动画效果.gif
#define centerX _currentBtn.frame.origin.x //_currentBtn 的X
#define centerY _currentBtn.frame.origin.y //_currentBtn 的Y
#define btnWHalf btnW / 2
#define adjushY  20.
#define space 10.  //子btn 间距
#define margin 20. //子、父btn 距离
#define btnW 20.
#define btnCount 5
#define LeftCount 2

写的有点 匆忙 ,没有单独封装到UIView上,所以大家 将就 用宏代替接口吧!!!哈哈哈

centerY和centerX来设置 父 按钮 origin的x和y,
通过改变它 会改变 所有子 按钮originx和y。btnCount是子 按钮的总数,LeftCount则是影响水平子按钮左右显示的数量。

typedef void (^createPointLeft)(BOOL, NSInteger index);
typedef void (^createPointRight)(BOOL, NSInteger index);
定义两个没有返回值的block用来保存要重用的代码,左弹出 、右弹出的动画效果我们是要在水平弹出中复用的。

@property (nonatomic, assign)NSTimeInterval currentTime;用来保存每次执行动画前的当前时间,以便确定每个按钮动画执行的时机。

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(((0.5/(float)_btnMarr.count * (float)_btnMarr.count )) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _currentBtn.enabled = YES;
    });
  • 这段代码为的是解决按钮快速点击,导致动画未执行完成,再次生成动画的bug。按钮点下后取消点击事件,延长的时间略长于动画组执行的时间。而后激活点击事件。
self.pointLeft = ^(BOOL sure, NSInteger index){
        startPoint = _currentBtn.isSelected ? CGPointMake(centerX -btnWHalf, centerY +adjushY - btnWHalf) : CGPointMake(centerX -btnWHalf - index * (btnW + space) - margin, centerY +adjushY - btnWHalf);
        endPoint = _currentBtn.isSelected ? CGPointMake(centerX - btnWHalf - index * (btnW + space) - margin, centerY +adjushY - btnWHalf) : CGPointMake(centerX +btnWHalf, centerY +adjushY - btnWHalf);
    };
 case animationTypeShowLeft:{
            self.pointLeft(YES,index);
            break;
        }
        case animationTypeShowRight:{
            self.pointRight(YES,index);
            break;
        }
        case animationTypeShowLevel:
            if (index <= LeftCount) {
                self.pointLeft(YES,index);
            }else{
                self.pointRight(YES,index - LeftCount - 1);
            }
            break;
        default:
            break;

  • 以上代码截图,显示的是block代码保存区的复用。block 执行前要给予空间。之后执行,空间中的代码,并传入参数。

动画分明细

  CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
        positionAnimation.duration=.3;
        positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        positionAnimation.fromValue = [NSValue valueWithCGPoint:startPoint];
        positionAnimation.toValue = [NSValue valueWithCGPoint:endPoint];
        
        CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
        scaleAnimation.additive = YES;
        scaleAnimation.values = @[@0,@(-1),@0];
        scaleAnimation.keyTimes =_currentBtn.isSelected ? @[@0,@0,@1] : @[@0,@1,@1];
        scaleAnimation.duration=.3;
        CAAnimationGroup *animationGG = [CAAnimationGroup animation];
        animationGG.duration = .3;
        animationGG.repeatCount = 1;
        animationGG.animations = @[positionAnimation, scaleAnimation];
        animationGG.fillMode = kCAFillModeBoth;
        animationGG.removedOnCompletion = YES;
        animationGG.beginTime =  _currentTime + (0.3/(float)_btnMarr.count * (float)i);
        [btn.layer addAnimation:animationGG forKey:nil];
        btn.layer.position = endPoint;

  • 按钮点击位移与 缩放同时进行。timingFunction意味着位移起始点、结束点之间运动的时间函数。代码中的函数 ,表示的是加速度越来越快。
  • 缩放 使用帧动画 无论 弹出还是 收复,我们的形变都是缩小到无回复到正常。additive将动画添加到mode当前显示层,以便复用。values形变值。keyTimes每次形变值处在的时间轴。fillMode结束的动画样式我们要保留。保留样式选择头尾保留,这里的动画首位不一致呢。removedOnCompletion动画结束后删除 渲染。防止动画再次执行重复的添加。
    • btn.layer.position = endPoint;改变控件 frame ,保持动画结束 后与 视图显示 的一致性。

这里强调一点position对应的是视图在父视图中锚点所处的位置而 我们的锚点默认的是{0.5,0.5}

github源代码

有问题反馈

在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容