Home > OS >  Allow touch only after button is pressed
Allow touch only after button is pressed

Time:10-30

In my last question I learned to put a timer on the game so that after the start button was clicked, the user would have to wait a few seconds to be able to touch the screen. That code looks like this:

self.view?.isUserInteractionEnabled = false
    DispatchQueue.main.asyncAfter(deadline: .now()   4.0) {
        self.view?.isUserInteractionEnabled = true
        
    }

I have kept the last post up for learning purposes for others. This time I am wondering how you would go about not allowing touch at all until a button is pressed! I switched the true statement above to "false", so the user cannot touch when first on the game. However, I want the user to be able to click the start button to then allow all other touch during the game. Thanks!

CodePudding user response:

A very simple way you could do this would be to create a subclass of UIView that overrides func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?.

Then you simply check to see if the button has been pressed before forwarding events to other subviews.

class View: UIView {
    
    private var hasTappedButton = false
    let button = UIButton()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        configureButton()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configureButton()
    }
    
    private func configureButton() {
        button.addTarget(self, action: #selector(tappedButton), for: .touchUpInside)
    }
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        
        let view = super.hitTest(point, with: event)
        
        guard !hasTappedButton else { return view }
        
        return view == button ? button : nil
    }
    
    @objc private func tappedButton() {
        hasTappedButton = true
    }
}

CodePudding user response:

I want the user to be able to click the start button to then allow all other touch during the game

My solution is to place an invisible view in front of the entire interface and use hit-test munging so that only one view behind it (self.passthruView, your button) is touchable:

class MyView: UIView {
    weak var passthruView : UIView?
    override func hitTest(_ point: CGPoint, with e: UIEvent?) -> UIView? {
        if let pv = self.passthruView {
            let pt = pv.convert(point, from: self)
            if pv.point(inside: pt, with: e) {
                return nil
            }
        }
        return super.hitTest(point, with: e)
    }
}

So as long as MyView is sitting (invisibly) in front of the whole interface, only the button can be touched. Then you take away MyView and the whole interface becomes touchable again.

  • Related