简体   繁体   中英

How can I detect a tap event in a child class of UIView?

I'm creating an app with swift. I've made child classes from UIView . After making them and writing some processes there, I feel that I want them to detect touch events.

But they aren't children of UIButton . I'd not like to force them to detect touch events using UIGestureRecognizer . Because UIGestureRecognizer needs to be used in UIViewController . I'd like to write codes of detecting touch just in the view.

Are there any ways to detect touch events just in UIView ?

You can simply add the gesture to the subclass of UIView as other said, but if you want to include the gesture within the definition of the subclass and make it more modular, you can use the notification dispatch mechanism to broadcast the gesture to the registered view controller.

First, you create a name for the notification:

extension Notification.Name {
    static let CustomViewTapped = Notification.Name("CustomViewTapped")
}

Then, you add the gesture to your custom view:

class CustomView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        let tap = UIGestureRecognizer(target: self, action: #selector(tapped))
        self.addGestureRecognizer(tap)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    @objc func tapped(_ sender: UIGestureRecognizer) {
        NotificationCenter.default.post(name: .CustomViewTapped, object: self)
    }
}

And, finally, observe the broadcast from your view controller:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(customViewTapped), name: .CustomViewTapped, object: nil)
        
        let customView = CustomView()
        self.view.addSubview(customView)
    }
    
    @objc func customViewTapped(_ sender: UIGestureRecognizer) {
    
    }
}

You can add UIGestureRecognizer to UIView. Another way you can add invisible UIButton on top of your UIView.

If you use UIView subclass, you can use something following and handle tap in action closure

class TappableView: UIView {

    var action: (()->())? = nil

    init(frame: CGRect) {
        super.init(frame: frame)
        initialization()
    }

    func initialization() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        addGestureRecognizer(tapGesture)
    }

    @objc private func tapGesture() {
        action?()
    }
}
class childView: UIView {
var action: (()->())? = nil

init(frame: CGRect) {
    super.init(frame: frame)
    initialization()
}

func initialization() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    addGestureRecognizer(tapGesture)
}

@objc private func tapGesture() {
    //Action called here 
}
}
    //MARK:- View Tap Handler
extension UIView {
    private struct OnClickHolder {
        static var _closure:()->() = {}
    }

    private var onClickClosure: () -> () {
        get { return OnClickHolder._closure }
        set { OnClickHolder._closure = newValue }
    }

    func onTap(closure: @escaping ()->()) {
        self.onClickClosure = closure

        isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
        addGestureRecognizer(tap)
    }

    @objc private func onClickAction() {
        onClickClosure()
    }
}

Usage:

    override func viewDidLoad() {
    super.viewDidLoad()
    let view = UIView(frame: .init(x: 0, y: 0, width: 80, height: 50))
    view.backgroundColor  = .red
    view.onTap {
        print("View Tapped")
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM