动画完成后无法单击 UIButton(以编程方式显示)

Posted

技术标签:

【中文标题】动画完成后无法单击 UIButton(以编程方式显示)【英文标题】:Can't click on UIButton (that appears programmatically) after animation gets done 【发布时间】:2013-04-29 00:54:44 【问题描述】:

刚刚问了一个小问题。我正在尝试使 UIButton 以编程方式出现,我必须对其进行动画处理。但是一旦动画完成,由于某种原因我无法点击按钮。

我有一个 CALayer“animationLayer”作为 UIView 的子层,在该 animationLayer 中,我有三个 CAShapeLayers“pathLayers”(我用它来动画三种不同的路径方式,如下图所示)。在这些 pathLayers 中,我添加了三个按钮作为它们各自的子层,这样我就可以制作一个动画,其中按钮在路径绘制自身时沿着路径移动。在我尝试添加一个按钮作为 pathLayer 的子层之前,一切都运行良好。现在,当我单击按钮时,它应该转到登录控制台窗口“按钮已被按下”的方法。我已经尝试将 self.view.userInteractionenabled 设置为 YES 但这仍然没有给我任何东西。

为什么我不能点击?

以下是代码的一些相关部分:

- (void)viewDidLoad

    [super viewDidLoad];

    self.animationLayer = [CALayer layer];
    self.animationLayer.frame = CGRectMake(20.0f, 64.0f, 
    CGRectGetWidth(self.view.layer.bounds) - 40.0f, CGRectGetHeight(self.view.layer.bounds) - 84.0f);

    [self.view.layer addSublayer:self.animationLayer];


- (id)createUIButtonwithXPosition:(CGFloat)x YPosition:(CGFloat)y Width:(CGFloat)width Height:(CGFloat)height

    UIImage *lionImage = [UIImage imageNamed:@"noun_project_347_2.png"];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self
               action:@selector(logger:)
     forControlEvents:UIControlEventTouchUpInside];
    button.frame = CGRectMake(x, y, width, height);
    button.userInteractionEnabled = YES;
//    [button setBackgroundColor:[UIColor clearColor]];
    [button setBackgroundImage:lionImage forState:UIControlStateNormal];
    [self.view addSubview:button];

    return button;



- (void)setupDrawingLayer

    if(self.pathLayer != nil)
        [self.pathLayer removeFromSuperlayer];
        [self.secondPathLayer removeFromSuperlayer];
        [self.thirdPathLayer removeFromSuperlayer];

        self.pathLayer = nil;
        self.secondPathLayer = nil;
        self.thirdPathLayer = nil;

        ...//Other code not relevant


    CGRect pathRect = CGRectInset(self.animationLayer.bounds, 100.0f, 100.0f);
    CGPoint bottomCenter = CGPointMake(CGRectGetMidX(pathRect), (self.lionBtnVerticalAlignment.constant + self.lionBtnHeight.constant + 25.0f));
    CGPoint center = CGPointMake(CGRectGetMidX(pathRect), CGRectGetMidY(pathRect));
    CGPoint leftCenter = CGPointMake(CGRectGetMinX(pathRect), CGRectGetMidY(pathRect));
    CGPoint rightCenter = CGPointMake(CGRectGetMaxX(pathRect), CGRectGetMidY(pathRect));


    UIBezierPath *path = [UIBezierPath bezierPath];

    UIBezierPath *secondPath = [UIBezierPath bezierPath];

    UIBezierPath *thirdPath = [UIBezierPath bezierPath];


    [path moveToPoint:bottomCenter];
    [path addLineToPoint:center];

    [secondPath moveToPoint:bottomCenter];
    [secondPath addLineToPoint:leftCenter];

    [thirdPath moveToPoint:bottomCenter];
    [thirdPath addLineToPoint:rightCenter];

    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.frame = self.animationLayer.bounds;
    pathLayer.bounds = pathRect;
    pathLayer.geometryFlipped = YES;
    pathLayer.path = path.CGPath;
    pathLayer.strokeColor = [UIColor blackColor].CGColor;
    pathLayer.fillColor = nil;
    pathLayer.lineWidth = 3.0f;
    pathLayer.lineDashPattern = [NSArray arrayWithObjects:
                                 [NSNumber numberWithInt:6],
                                 [NSNumber numberWithInt:2],
                                 nil];
    pathLayer.lineJoin = kCALineJoinBevel;


    CAShapeLayer *secondPathLayer = [CAShapeLayer layer];
    secondPathLayer.frame = self.animationLayer.bounds;
    secondPathLayer.bounds = pathRect;
    secondPathLayer.geometryFlipped = YES;
    secondPathLayer.path = secondPath.CGPath;
    secondPathLayer.strokeColor = [UIColor redColor].CGColor;
    secondPathLayer.fillColor = nil;
    secondPathLayer.lineWidth = 3.0f;
    secondPathLayer.lineDashPattern = [NSArray arrayWithObjects:
                                 [NSNumber numberWithInt:6],
                                 [NSNumber numberWithInt:2],
                                 nil];
    secondPathLayer.lineJoin = kCALineJoinBevel;

    CAShapeLayer *thirdPathLayer = [CAShapeLayer layer];
    thirdPathLayer.frame = self.animationLayer.bounds;
    thirdPathLayer.bounds = pathRect;
    thirdPathLayer.geometryFlipped = YES;
    thirdPathLayer.path = thirdPath.CGPath;
    thirdPathLayer.strokeColor = [UIColor greenColor].CGColor;
    thirdPathLayer.fillColor = nil;
    thirdPathLayer.lineWidth = 3.0f;
    thirdPathLayer.lineDashPattern = [NSArray arrayWithObjects:
                                       [NSNumber numberWithInt:6],
                                       [NSNumber numberWithInt:2],
                                       nil];
    thirdPathLayer.lineJoin = kCALineJoinBevel;

    [self.animationLayer addSublayer:pathLayer];
    [self.animationLayer addSublayer:secondPathLayer];
    [self.animationLayer addSublayer:thirdPathLayer];

    self.pathLayer = pathLayer;
    self.secondPathLayer = secondPathLayer;
    self.thirdPathLayer = thirdPathLayer;


    UIImage *lionImage = [UIImage imageNamed:@"noun_project_347_2.png"];

    btn1 = (UIButton *)[self createUIButtonwithXPosition:0.0f YPosition:0.0f Width:lionImage.size.width Height:lionImage.size.height];
    btn1.layer.anchorPoint = CGPointZero;
    btn1.layer.frame = CGRectMake(0.0f, 0.0f, lionImage.size.width, lionImage.size.height);

    [self.view bringSubviewToFront:btn1];
    self.view.userInteractionEnabled = YES;

    ....//Other code not relevant




- (void)startAnimation

    [self.pathLayer removeAllAnimations];
    [self.secondPathLayer removeAllAnimations];
    [self.thirdPathLayer removeAllAnimations];

     ....//Other code not relevant

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.duration = 3.0;
    pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
    pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];

    [self.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
    [self.secondPathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
    [self.thirdPathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];

    CAKeyframeAnimation *lionAnimation = [CAKeyframeAnimation     animationWithKeyPath:@"position"];
    lionAnimation.duration=3.0;
    lionAnimation.path = self.pathLayer.path;
    lionAnimation.calculationMode = kCAAnimationPaced;
    lionAnimation.delegate = self;

    [btn1.layer addAnimation:lionAnimation forKey:@"position"];

    btn1.layer.position = CGPointMake(365.0, 460.0);

【问题讨论】:

您确定点击365.0, 460.0(无论按钮是否出现)不起作用? 是的,先生,我很确定。 【参考方案1】:

在我看来,您可能会遇到一个典型的问题,其中 UIView 是另一个 UIView 的子孩子,但超出了它的范围。要检查是否是这种情况,请将父视图的属性设置为setClipsToBounds:YES,您很可能会看到按钮消失。查看此帖子了解更多详情:My custom UIView dos not receive touches

如果是这种情况,您有几个选择。

    将按钮放置在父视图范围内的位置!!

    子类化父视图并将以下代码添加到 is 以便其子视图即使在父视图边界之外也可以响应触摸。

    -(UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event

    UIView* 结果 = [super hitTest:point withEvent:event]; 如果(结果) 返回结果; for (UIView* sub in [self.subviews reverseObjectEnumerator]) CGPoint pt = [self convertPoint:point toView:sub]; 结果 = [sub hitTest:pt withEvent:event]; 如果(结果) 返回结果; 返回零;

【讨论】:

嘿哈维尔!我尝试了整个 setClipsToBounds:YES 过程,但显然情况并非如此。按钮的图像仍然存在。我现在想做的是使用图像来制作整个动画,一旦动画完成,我将删除相应的图层,并在图层结束动画的同一位置将每个图层替换为 UIButton。这是一个好方法还是您有其他想法?【参考方案2】:

请试试这个:

[button setBackgroundImage:lionImage forState:UIControlEventTouchUpInside];

【讨论】:

嘿!我试过这样做,但它只会让图像消失,它对点击问题没有做任何事情。还有其他建议吗? 当你按右时,上面的代码可以工作吗?带有日志消息“按钮已被按下” 不,问题是我无法点击按钮。因此,它甚至不会转到按钮的操作方法(按下时)。我认为因为我在 CALayer 中有一个 UIButton,所以该按钮位于图层的背面,因此无法按下(至少我是这么认为的)。因为 UIView 本身可以看作是一个 CALayer,所以我想做的应该不难..lol,但由于某种原因,我无法使 Button 可点击。

以上是关于动画完成后无法单击 UIButton(以编程方式显示)的主要内容,如果未能解决你的问题,请参考以下文章

在 UIButton 单击时以编程方式创建 Segue 或推送到另一个视图控制器

更改以编程方式创建的单击 UIButton 的背景图像

对于以编程方式创建的 UIButton,有时不会触发按钮单击事件

无法单击 UIButton iphone

Swift:以编程方式在 UICollectionViewCell 中的 IndexPath 中的多个 UIButton,下一个 addTarget 不单击

点击 UIButton 以编程方式创建另一个 UIButton