开发者

How can I forward touches to a UIButton from another UIView?

I have a UIButton and a UIView. The View sits above the button, and is larger than the button in size. The view itself is what I want to have accept the touch events, and I'd like to forward them to the button, so that all the normal button visual changes on touch happen.

I can't seem to make this work-- my UIView implements touchesBegan/Moved/Ended/Cancelled, and turns around开发者_开发百科 and calls the same methods on the button with the same arguments. But the button doesn't respond.

I have ensured that the touch methods are in fact being called on the UIView.

Is there something obvious I'm missing here, or a better way of getting the control messages across? Or is there a good reason why this shouldn't work?

Thanks!

[Note: I'm not looking for workarounds for the view+button design. Let's assume that that's a requirement. I'm interested in the notion of controls that are touch proxies for other controls. Thanks.]


Create a ContainerView that contains a button and override hitTest:withEvent: so that it returns the UIButton instance.


Are you sure your methods are being called? If you haven't set userInteractionEnabled=YES, then it won't work.

I've used such touch-forwarding before without problems, though, so I don't know why you're seeing the problems you're seeing.


I use the small class below when I need a larger touch target than the visual size of the button.

Usage:

let button = UIButton(...) // set a title, image, target/action etc on the button
let insets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
let buttonContainer = TouchForwardingButtonContainer(button: button, insets: insets) // this is what you add to your view
// a container view for a button that insets the button itself but forwards touches in the inset area to the button
// allows for a larger touch target than the visual size of the button itself
private class TouchForwardingButtonContainer: UIView {
    private let button: UIButton

    init(button: UIButton, insets: UIEdgeInsets) {
        self.button = button

        super.init(frame: .zero)

        button.translatesAutoresizingMaskIntoConstraints = false
        addSubview(button)
        let constraints = [
            button.topAnchor.constraint(equalTo: topAnchor, constant: insets.top),
            button.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -insets.bottom),
            button.leftAnchor.constraint(equalTo: leftAnchor, constant: insets.left),
            button.rightAnchor.constraint(equalTo: rightAnchor, constant: -insets.right)
        ]
        NSLayoutConstraint.activate(constraints)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("NSCoding not supported")
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        return button
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜