如何点击运动中的Button(控件)

这个问题是在之前做项目的时候遇到的,今天就顺便总结并扩展一下,由于界面动画比较多,需要点击运动中的button,在网上找了很久也没找到合适的答案,最后在解决其他问题时发现此问题的解决方案,首先还是先说明下常用的动画:

  • Core Animation动画实现位移效果
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(100, 100, 50, 50);
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];

     //创建basic位移动画
    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    //起点,fromValue是对象类型,所以CGPoint必须封装成对象
    basicAnimation.fromValue = [NSValue valueWithCGPoint:button.center];
    //到哪个点,记得移动的是视图的中心点
    basicAnimation.toValue   = [NSValue valueWithCGPoint:CGPointMake(100, 550)];
    //动画运行总时间
    basicAnimation.duration  = 3.0;
    //重复次数
//    basicAnimation.repeatCount = MAXFLOAT;
    //是否倒退
//    basicAnimation.autoreverses = YES;
    //设置为线性移动
    basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    //设置视图在动画结束后停留在结束位置,这两个代码同时设置才有效果
    basicAnimation.fillMode = kCAFillModeForwards;
    basicAnimation.removedOnCompletion = NO;

    //加载动画 注意这里是layer层的动画
    [button.layer addAnimation:basicAnimation forKey:nil];

}

- (void)click:(UIButton *)button {
    NSLog(@"click");
}

运行程序点击button,你会发现,只有在初始化的那个位置是能够点击到的,并不能实现点击运动中的button

这里只需要添加一个类CADisplayLink,具体解释看代码实现

 - (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(100, 100, 50, 50);
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    button.tag = 1000;
    [self.view addSubview:button];

    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    //可以不写fromValue
    //起点,fromValue是对象类型,所以CGPoint必须封装成对象
    basicAnimation.fromValue = [NSValue valueWithCGPoint:button.center];
    //到哪个点
    basicAnimation.toValue   = [NSValue valueWithCGPoint:CGPointMake(100, 550)];
    //动画运行总时间
    basicAnimation.duration  = 100.0;
    //重复次数
//    basicAnimation.repeatCount = MAXFLOAT;
    //是否倒退
//    basicAnimation.autoreverses = YES;
    //设置为线性移动
    basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

    //设置视图在动画结束后停留在结束位置,这两个代码同时设置才有效果
    basicAnimation.fillMode = kCAFillModeForwards;
    basicAnimation.removedOnCompletion = NO;

    //加载动画 注意这里是layer层的动画
    [button.layer addAnimation:basicAnimation forKey:nil];

    //创建CADisplayLink类,iPhone6中等同于屏幕刷新频率为60hz,也就是每秒调用60次displaylinkHandle方法,Pop动画看起来很流畅,就是使用了此机制
    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displaylinkHandle)];
    //加入到RunLoop主事件中
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

}

 - (void)click:(UIButton *)button {
    NSLog(@"click");
}

 - (void)displaylinkHandle {
    //根据tag值获取到前面创建的button
    UIButton *getButton = (UIButton *)[self.view viewWithTag:1000];
    //获得button的layer层,这里一定是presentationLayer,不然layer不对应
    CALayer *layer = (CALayer *)[getButton.layer presentationLayer];
    //获取当前layer的中心点
    CGPoint point = [[layer valueForKey:@"position"] CGPointValue];
    getButton.layer.position = point;
}

现在点击移动中的button,可以看到控制台会不断打印消息,如此便能实现点击效果,这个只是简单的位移动画,要是动画按照贝塞尔曲线运动,view位移动画,或者是仿射变换又该如何操作,贝塞尔曲线运动和位移处理大体相同,就不在赘述了,要是真不会,就给我留言,下面就说说其他两种动画

  • view位移动画
    由于此动画必须是在动画结束时才能进行点击,所以如果要点击移动中的控件,需要将动画暂停,然后触发点击事件,再进行动画,理论上是可行的,一般来说如果需要位移动画完全可以通过layer层动画完成。

  • 仿射变换
    以中心点为圆心,在圆周上运动

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(100, 100, 30, 30);
    button.center = self.view.center;
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    button.tag = 1000;
    //设置锚点
    button.layer.anchorPoint = CGPointMake(-2, -2);
    [self.view addSubview:button];


    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkHandle)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

}

- (void)click:(UIButton *)button {
    NSLog(@"click");
}


- (void)displayLinkHandle {
    UIButton *getButton = (UIButton *)[self.view viewWithTag:1000];

    getButton.layer.transform = CATransform3DRotate(getButton.layer.transform, M_PI * 2 * (1.0 / 360.0), 0, 0, 1);

}

总结:在遇到问题过程中,需要学会总结,并举一反三才能扩展更多的知识,在使用CADisplayLink类时,需要记的它的方法是每秒调用60次,使用对象方法[displayLink invalidate];可以停止调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值