基础

动画过程中响应事件

2016-07-18  本文已影响412人  c048e8b8e3d7

案列

有一个button通过动画移动到另外一个位置,希望可以在移动的过程中也能点击按钮做某件事,一般情况下我们会按照下面的方法处理

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化按钮
    button       = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    // 执行动画
    [UIView animateWithDuration:10.f
                          delay:0
                        options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                         button.frame = CGRectMake(0, 468, 100, 100);
                     } completion:^(BOOL finished) {
                         
    }];
}

- (void)buttonEvent:(UIButton *)button {
    NSLog(@"do something);
}

然后在实际过程中,发现真实的情况是这样的:

  1. 在移动过程中单击按钮是没有Log输出的
  2. 单击按钮动画的终点位置(就算此时按钮在界面上的位置离终点还很远)是有Log输出的
    然而这并不是我们想要的

分析

在动画过程中界面上显示移动的是layer中的presentationLayer,而layer中的modelLayer在动画开始的那一瞬间,frame已经变成CGRectMake(0, 468, 100, 100)
换句话说,动画效果是presentationLayer改变位置的结果,而modelLayer是没有动画效果的

解决方法

touchesBegan方法中去判断当前点击的点是否在presentationLayerframe里面,在这之前应该做如下两件事

  1. 注释buttonaddTarget方法(不然会出现上面提到的情况2)
  2. 设置button.userInteractionEnabled = NO(不然在终点处button的单击会阻止触摸事件)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    CALayer *presentationLayer = button.layer.presentationLayer;
    CALayer *modelLayer = button.layer.modelLayer;
    NSLog(@"%@", NSStringFromCGRect(presentationLayer.frame));
    NSLog(@"%@", NSStringFromCGRect(modelLayer.frame));
    
    //判断这个点是否在presentationLayer里面
    CGPoint point = [[touches anyObject] locationInView:self.view];
    if (CGRectContainsPoint(presentationLayer.frame, point)) {
        [self buttonEvent:nil];
    }
}
上一篇下一篇

猜你喜欢

热点阅读