首次点击后,UIButton无法点击

时间:2017-09-04 19:04:35

标签: ios swift3 xcode8

我试图在点击按钮时从底部带来子视图。但只是第一次按钮是可点击的。在动画按钮无法点击后进行第二次点击。

这是代码。

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")
    } 
}

首次出现屏幕时:

enter image description here

最初,按钮是可点击的,当点击它时,它会随着子视图一起向上移动。 enter image description here

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

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

self.addSubview(按钮)

enter image description here

1 个答案:

答案 0 :(得分: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)   
    }

这个条件:

  

button.bounds.contains(pointForTargetView)

动画后按下按钮时返回false。

所以,我需要在子视图上捕获触摸事件,这是超视图框架。

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

Swift 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
}

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

enter image description here

单击该按钮时,mainView向上动画,按钮向上移动,因为它是mainView的子视图。

enter image description here

再次单击按钮时,mainView将转到上一个位置,按钮也是如此。

enter image description here