使用UIView animateWithDuration动画时无法触摸UIButton

2020/12/12 05:52 · ios ·  · 0评论

我有以下代码:

[UIView animateWithDuration:0.3
                      delay:0.0
                    options:UIViewAnimationCurveEaseOut | UIViewAnimationOptionAllowUserInteraction
                 animations:^{
                     CGRect r = [btn frame];
                     r.origin.y -= 40;
                     [btn setFrame: r];
                 }
                 completion:^(BOOL done){
                     if(done){
                         [UIView animateWithDuration:0.3
                                               delay:1
                                             options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction
                                          animations:^{
                                              CGRect r = [btn frame];
                                              r.origin.y += 40;
                                              [btn setFrame: r];
                                          }
                                          completion:^(BOOL done){if(done) zombiePopping = 0; }];
                     }

                 }];

问题是,即使我正在使用UIViewAnimationOptionAllowInteraction按钮似乎在动画时也不会响应触摸,这对我来说有点奇怪。

也许这可以通过Core Animation来完成?如果是这样,我将如何处理?

当对其进行动画处理时,按钮的可触摸部分将与按钮的可见框架不一致。

在内部,按钮的帧将设置为动画的最终值。您应该会发现您可以在该区域中轻按,它将起作用。

要点击移动的按钮,您需要对按钮的.layer.presentationLayer属性进行点击测试(需要导入QuartzCore框架才能执行此操作)。通常,这可以通过视图控制器中的触摸处理方法来完成。

如果您需要更多,我很乐意扩展此答案。

这是通过点击测试演示层来响应触摸事件的方式。此代码在管理按钮的视图控制器子类中。当我这样做时,我对初始触摸而不是触摸结束(这通常是在轻击会记录时)感兴趣,但是原理是相同的。

记住要导入QuartzCore框架并将其添加到您的项目中。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:self.view];
    for (UIButton *button in self.buttonsOutletCollection)
    {
        if ([button.layer.presentationLayer hitTest:touchLocation])
        {
            // This button was hit whilst moving - do something with it here
            break;
        }
    }
}

迅捷5

就我而言,设置button.alpha = 0为时,无论是否设置UIViewAnimationOptionAllowUserInteraction为选项,按钮交互都将停止

原因

无论您是否定义动画,视图的属性都会立即应用于视图的图层因此,设置时view.alpha=0,您将view完全隐藏

简单,只需减少alpha=0.1(甚至0.05

UIView.animate(withDuration: 2,
                       delay: 0,
                       options: [.allowUserInteraction, .overrideInheritedOptions, .curveEaseOut, .repeat, .autoreverse],
                       animations: {
                           self.button.layer.opacity = 0.01 // 0.0 will make the button unavailable to touch
        })

选项的顺序很重要,您必须先放置UIViewAnimationOptionAllowUserInteraction,然后再添加其他选项。

在Swift 3中使用: .allowUserInteraction

我已经使用NSTimer实现了这一点:首先,执行开始动画,然后您应该启动一个计时器,这是演示代码:

-(void)fun···
{
    [UIView animateWithDuration:0.3
                      delay:0.0
                    options:UIViewAnimationCurveEaseOut |  UIViewAnimationOptionAllowUserInteraction
                 animations:^{
                     CGRect r = [btn frame];
                     r.origin.y -= 40;
                     [btn setFrame: r];
                 }
                 completion:^(BOOL done){}];

    then , you should start an timer,example:
    //start timer
   if (timer != nil)
   {
       [timer invalidate];
       timer = nil;
   }
   [self performSelector:@selector(closeButton) withObject:nil afterDelay:0];
}


- (void)closeButton
{
    if (timer != nil)
    {
        return;
    }

    //start timer
    timer = [NSTimer scheduledTimerWithTimeInterval:1.5f target:self selector:@selector(timerEvent) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}

- (void)timerEvent
{
    [UIView animateWithDuration:0.3
                                               delay:1
                                             options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction
                                          animations:^{
                                              CGRect r = [btn frame];
                                              r.origin.y += 40;
                                              [btn setFrame: r];
                                          }
                                          completion:^(BOOL done){if(done) zombiePopping = 0; }];
    [timer invalidate];
    timer = nil;
}

对于懒惰,在Swift(2.0)中的答案相同。如有必要,请替换为回路和插座集合:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first
    let touchLocation = touch!.locationInView(self.view)
    if self.button.layer.presentationLayer()!.hitTest(touchLocation) != nil {
        action() // Your action, preferably the original button action.
    }
}

Swift 3.0
在viewdidload的顶部创建一个超级视图

let superView = UIView(frame: view.frame)
    superView.isUserInteractionEnabled = true
    superView.backgroundColor = UIColor.clear
    superView.alpha = 0.1
    view.addSubview(superView)

现在像这样实现touchesbagan

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    guard let touch = (touches as NSSet).anyObject() as? UITouch else {
        return
    }

    let touchLocation = touch.location(in: self.view)
    if btnone.layer.presentation()?.hitTest(touchLocation) != nil {
        print("1") // Do stuff for button 
    }
    if btntwo.layer.presentation()?.hitTest(touchLocation) != nil {
        print("2") // Do stuff
    }
    if btnthree.layer.presentation()?.hitTest(touchLocation) != nil {
        print(3) // Do stuff
    }
    if btnfour.layer.presentation()?.hitTest(touchLocation) != nil {
        print(4) // Do stuff
    }
}

如果您有UIButton的子类,最简单的方法是通过覆盖hitTest

public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        return self.layer.presentation()?.hitTest(self.convert(point, to: superview)).flatMap { _ in return self } ?? nil
    }

迅捷版本:
“ 999”是用于标识目标视图的标记值。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = touches.first
        let touchLocation = (touch?.locationInView(self.rootView))!

        for view in self.view.subviews {
            if let layer = view.layer.presentationLayer()?.hitTest(touchLocation) where view.tag == 999 {
                // Here view is the tapped view
                print(view)
            }
        }
    }

奇迹般有效

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
if bounds.contains(point) && !hidden && userInteractionEnabled && enabled {
return self
}
return super.hitTest(point, withEvent: event)
}

虽然这个答案也是正确的

我在屏幕上有4个按钮,这些按钮应该用作向左,向右,向下和向上导航。我使用来自@ nahung89答案的简单技巧,并添加了完成功能以获得所需的完整效果。这是代码:

  1. 将所有按钮连接到ViewController中的插座集合

    @IBOutlet var navigationButtons: [UIButton]!
    
  2. 在viewDidAppear中添加了此功能:

        navigationButtons.forEach { button in
            UIView.animate(withDuration: 0.5,
                                    delay: 5,
                                    options: [.curveLinear, .allowUserInteraction],
                                    animations: {
                                        button.alpha = 0.1
            }) { _ in button.alpha = 0 }
        }
    
本文地址:http://ios.askforanswer.com/shiyonguiview-animatewithdurationdonghuashiwufachumouibutton.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!