按钮锚定到InputAccessoryView仅在其框架中工作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按钮锚定到InputAccessoryView仅在其框架中工作相关的知识,希望对你有一定的参考价值。

建立

我通过以下方式在inputAcessoryView中实施了UIViewController

override var inputAccessoryView: UIView? {

    get {

        return bottomBarView
    }
}
override var canBecomeFirstResponder: Bool {

    return true
}

fileprivate lazy var bottomBarView: UIView = {

    let view = UIView()
    let separatorLineView = UIView()

    view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height / 9)
    view.backgroundColor = .white

    /...

    separatorLineView.backgroundColor = UIColor(r: 220, g: 220, b: 220, a: 1)
    separatorLineView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(separatorLineView)
    separatorLineView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    separatorLineView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    separatorLineView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    separatorLineView.heightAnchor.constraint(equalToConstant: 1).isActive = true

    view.addSubview(self.photoButton)
    self.photoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    self.photoButton.centerYAnchor.constraint(equalTo: separatorLineView.centerYAnchor, constant: -12).isActive = true
    self.photoButton.widthAnchor.constraint(equalToConstant: view.frame.width / 4.5).isActive = true
    self.photoButton.heightAnchor.constraint(equalToConstant: view.frame.width / 4.5).isActive = true

    return view
}()

photoButton.touchUpInside实施了一项行动。

问题

该按钮只能在inputAccessoryView框架中包含的部分中点击:如果我在外面的部分点击它,则没有任何反应。

有没有快速的方法让它像这样工作?

我尝试将photoButton移出bottomBarView并将其添加到视图中但是:

  • 我需要photoButton“锚定”到inputAccessoryView,但似乎inputAccessoryView在视图中没有锚属性? (我只能通过爆炸解开来访问他们的frame属性)
  • 当我这样做时,photoButton部分隐藏在inputAccessoryView背后,我无法用view.bringSubview(ToFront:)推进它

提前致谢。

答案

在过去的几天里,我在自己的工作中遇到了这个问题。

你需要为你的hitTest实现自己的inputAcessoryView UIResponder方法。可能看起来像这样的东西:

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

    if self.photoButton.frame.contains(point) {
        return self.photoButton
    }

    return super.hitTest(point, with: event)
}

更多信息可以看到in this related question

另一答案

你有的问题是inputAccessoryView(你的bottomBarView)没有高度。因此,您添加的所有子视图都超出了它的范围。如果你要设置clipsToBounds = true,你会发现一切都消失了。

正如您所看到的,这个问题是,这些子视图没有获得触摸事件,因为它们超出了超级视图的范围。来自Apple的文档:

如果触摸位置位于视图边界之外,则hitTest:withEvent:方法将忽略该视图及其所有子视图。因此,当视图的clipsToBounds属性为NO时,即使它们恰好包含触摸,也不会返回该视图边界之外的子视图。

Understanding Event Handling, Responders, and the Responder Chain

解决方案是让inputAccessoryView成为正确的高度。 self.view.frame.height / 9在你的例子中是0,因为在你使用它时没有设置框架。

相反,创建一个UIView子类,具有以下重要部分:

class BottomBarView: UIView {

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

        autoresizingMask = .flexibleHeight

        let someView = UIView()
        addSubview(someView)
        someView.translatesAutoresizingMaskIntoConstraints = false
        someView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        someView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        someView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        someView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true

        // In this case, the top, bottom, and height constraints will 
        // determine the height of the inputAccessoryView
        someView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    }

    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIViewNoIntrinsicMetric, height: 0)
    }
}

尝试添加按钮。你会看到它现在得到一个触摸事件,因为它现在在它的超级视图范围内。

以上是关于按钮锚定到InputAccessoryView仅在其框架中工作的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 从锚定到按钮框架的按钮点击动画到屏幕上

如何将对话框锚定到listview qt qml中的按钮

如何将浮动操作按钮锚定到App ToolBar,就像在指南图像中一样?

将 Windows 窗体工具提示锚定到鼠标

将 ImageView 锚定到折叠工具栏

如何将 UIAlertController 操作表锚定到特定单元格 UICollectionView?