UIButton 在第一次点击后不可点击

Posted

技术标签:

【中文标题】UIButton 在第一次点击后不可点击【英文标题】:UIButton is not clickable after first click 【发布时间】:2017-09-04 19:04:35 【问题描述】:

单击按钮时,我试图从底部带来一个子视图。但只有第一次按钮是可点击的。对于动画按钮后的第二次点击是不可点击的。

这里是代码。

class AnimateView: UIView 
var button: UIButton!
var menuView: UIView!
var mainView: UIView!

   override init(frame: CGRect) 
        super.init(frame: frame)
        mainView = UIView(frame: CGRect(x: 0, y: 0, width: 
        self.frame.size.width, height: self.frame.size.height))

        mainView.clipsToBounds = true
        mainView.backgroundColor = .clear
        mainView.isUserInteractionEnabled = true
        mainView.isExclusiveTouch = true
        self.addSubview(mainView)

        let theRect = CGRect(x: self.frame.size.width / 2 - 44 / 2, y: 0, 
        width: 44, height: 44)
        button = UIButton(frame: theRect)
        check.layer.cornerRadius = btnView.frame.size.height / 2
        mainView.addSubview(self.check)
        mainView.bringSubview(toFront: check)
        check.addTarget(self, action: #selector(buttonClick(_:)), 
        for:.touchUpInside)

        let newRect = CGRect(x: 0, y: check.frame.height, width: 
        self.frame.size.width, height: self.mainView.frame.size.height)
        menuView = UIView(frame: newRect)
        menuView.backgroundColor = .blue
        mainView.addSubview(menuView)



 required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    func buttonClick(_ sender: UIButton) 
        toggleMenu()
    


    func toggleMenu() 
        if check.transform == CGAffineTransform.identity 
            UIView.animate(withDuration: 1, animations: 
                self.check.transform = CGAffineTransform(scaleX: 12, y: 12)
                self.mainView.transform = CGAffineTransform(translationX: 0, y: -120)
                self.check.transform = CGAffineTransform(rotationAngle: self.radians(180)) // 180 is 3.14 radian
                self.setNeedsLayout()
            )  (true) in
                UIView.animate(withDuration: 0.5, animations: 

                )
            
         else 
            UIView.animate(withDuration: 1, animations: 
                // .identity sets to original position
                //self.btnView.transform = .identity
                self.mainView.transform = .identity
                self.button.transform = .identity
            )
        

    

这个类是从另一个这样的 UIView 类调用的

class MainViewClass: UIView 
     var animateView: AnimateView!

     override init(frame: CGRect) 
            animateView = AnimateView(frame: CGRect(x: 0, y: self.frame.size.height - 44 - 44 - 20, width: self.frame.size.width, height: 122+44))
            //animateView.clipsToBounds = true
            self.addSubview(animateView)
            self.bringSubview(toFront: animateView)
    

     required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
     

屏幕首次出现时:

按钮最初是可点击的,当它被点击时,它会随着子视图向上移动。

现在该按钮不可点击。当我看到按钮的框架时,它与屏幕最初出现时按钮触摸屏幕底部时相同,即使它向上移动。 我的意图是在单击按钮时从底部显示带有动画的屏幕,并在第二次单击时移动到默认位置。

但是,如果我将按钮作为子视图放置在 self 中,而不是作为 mainView 的子视图,则该按钮是可点击的,但即使在视图被动画化并向上移动后,它仍保持在相同的位置。

self.addSubview(按钮)

【问题讨论】:

您是否需要在完成动画后删除您的AnimateView,以便再次显示按钮? 首先当按钮被点击时,子视图应该从屏幕底部开始动画并且按钮也应该向上移动。然后第二次单击该按钮应与子视图一起下降。现在,当单击按钮时,子视图会向上动画,并且按钮的按钮不可单击。 当按钮被点击并向上移动时,它是不可点击的。虽然我尝试更新它的框架,但它无法点击。 【参考方案1】:

所以,我终于得到了我打算在动画前后实现的解决方案。

UIButton在动画后没有收到任何触摸事件的原因是动画后UIButton向上移动,因为它是mainView的子视图。因此,它超出了其 superView 的范围,并且不响应任何点击事件。虽然我将按钮连同它的 superView 一起移动,它是 mainView,但按钮没有响应触摸事件。 然后,我使用 hitTest 测试了按钮绑定是否在 mainView 内:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? 
        let pointForTargetView: CGPoint = button.convert(point, from: mainView)
        if button.bounds.contains(pointForTargetView) 
            print("Button pressed")
            return button.hitTest(pointForTargetView, with:event)
        
        return super.hitTest(point, with: event)   
    

这个if条件:

button.bounds.contains(pointForTargetView)

动画结束后按下按钮返回false。

所以,我需要在其父视图框架之外的子视图上捕获触摸事件。

使用 hitTest() 解决了我的问题。 这是帮助我的链接。 Capturing touches on a subview outside the frame of its superview using hitTest:withEvent:

斯威夫特 3

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? 

    if clipsToBounds || isHidden || alpha == 0 
        return nil
    

    for subview in subviews.reversed() 
        let subPoint = subview.convert(point, from: self)
        if let result = subview.hitTest(subPoint, with: event) 
            return result
        
    

    return nil

屏幕截图: 首次出现屏幕时,按钮位于屏幕底部,子视图隐藏在按钮下方。

当按钮被点击时,mainView 向上动画并且按钮向上移动,因为它是 mainView 的子视图。

当再次点击按钮时,mainView 会回到之前的位置,按钮也会。

【讨论】:

以上是关于UIButton 在第一次点击后不可点击的主要内容,如果未能解决你的问题,请参考以下文章

UIButton 在 ScrollView 上不可点击

UITableViewCell 中的 UIButton 不可点击

添加UITabbar时UIButton不可点击

UIView中的UIButton不可点击

UItableView Cell上的UIbutton不可点击

Swift:UIButton 不可点击,NSLayoutConstraint heightAnchor 问题