首页 > 解决方案 > Swift - 如何将触摸事件传递给多个按钮,这些按钮是第二个 UIWindow 的一部分,但忽略其他所有内容

问题描述

我按照这个答案创建了一个按钮,该按钮是位于所有其他窗口之上的第二个窗口的一部分。它适用于 1 个按钮,因为它只允许一个按钮获取触摸事件,忽略第二个窗口内的所有其他内容,但其下方的主窗口仍然接收所有触摸事件。

// This comment is from @robmayoff's answer
// As I mentioned, I need to override pointInside(_:withEvent:) so that the window ignores touches outside the button:

var button: UIButton?

private override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    guard let button = button else { return false }
    let buttonPoint = convertPoint(point, toView: button)
    return button.pointInside(buttonPoint, withEvent: event)
}

我现在在 SecondWindow 中拥有它的方式,我可以接收触摸事件,cancelButton但其他按钮与其他所有按钮一起被忽略。问题是我如何接收第二个窗口内其他按钮的触摸事件但仍然忽略其他所有内容?

第二个 UIWindow。这是我尝试过的,但没有奏效:

class SecondWindow: UIWindow {

    var cancelButton: UIButton?
    var postButton: UIButton? // I need this to also receive touch events
    var reloadButton: UIButton? // I need this to also receive touch events

    init() {
        super.init(frame: UIScreen.main.bounds)
        backgroundColor = nil
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

        if let cancelButton = cancelButton {
            let cancelButtonPoint = convert(point, to: cancelButton)
            return cancelButton.point(inside: cancelButtonPoint, with: event)
        }

        if let postButton = postButton {
            let postButtonPoint = convert(point, to: postButton)
            return postButton.point(inside: postButtonPoint, with: event)
        }

        if let reloadButton = reloadButton {
            let reloadButtonPoint = convert(point, to: reloadButton)
            return reloadButton.point(inside: reloadButtonPoint, with: event)
        }

        return false
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, with: event)
        guard let safeHitView = hitView else { return nil }
        if safeHitView.isKind(of: SecondController.self) { return nil }
        return safeHitView
    }

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

带有按钮的vc:

class SecondController: UIViewController {

    lazy var cancelButton: UIButton = { ... }()

    lazy var postButton: UIButton = { ... }()

    lazy var reloadButton: UIButton = { ... }()

    let window = SecondWindow()

    init() {
        super.init(nibName: nil, bundle: nil)

        window.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

        window.cancelButton = cancelButton
        window.postButton = postButton
        window.reloadButton = reloadButton

        window.isHidden = false
        window.backgroundColor = .clear
        window.rootViewController = self
        window.windowLevel = UIWindow.Level.normal
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .clear

        // Anchors for buttons
    }
}

标签: iosswiftuibuttontouch-eventuiwindow

解决方案


我检查触摸的点是否在接收器内部(无论触摸哪个按钮)。如果返回true,则确认触摸并且按钮响应,如果不是,则不执行任何操作并跳到下一个按钮,在那里检查并重复该过程,直到最后一个按钮并重复相同的过程。

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

    guard let cancelButton = cancelButton, let postButton = postButton, let reloadButton = reloadButton else {
        return false
    }

    let cancelButtonPoint = convert(point, to: cancelButton)
    let cancelBool = cameraButton.point(inside: cameraButtonPoint, with: event)
    if cancelBool {
        return cancelButton.point(inside: cancelButtonPoint, with: event)
    }

    let postButtonPoint = convert(point, to: postButton)
    let postBool = postButton.point(inside: postButtonPoint, with: event)
    if postBool {
        return postButton.point(inside: postButtonPoint, with: event)
    }

    let reloadButtonPoint = convert(point, to: reloadButton)
    return reloadButton.point(inside: reloadsButtonPoint, with: event)
}

推荐阅读