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

Posted

技术标签:

【中文标题】锚定到 InputAccessoryView 的按钮仅在其框架中工作【英文标题】:Button anchored to InputAccessoryView working only in its frame 【发布时间】:2017-03-03 09:27:07 【问题描述】:

设置

我通过以下方法在UIViewController 中实现了inputAcessoryView

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 在视图中没有锚属性? (我只能通过 bang unwrapping 访问他们的 frame 属性) 当我这样做时,photoButton 部分隐藏在inputAccessoryView 后面,我无法用view.bringSubview(ToFront:) 将其向前推进

提前致谢。

【问题讨论】:

【参考方案1】:

您遇到的问题是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)
    

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

【讨论】:

【参考方案2】:

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

您需要为您的inputAcessoryView 实现自己的hitTest 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。

【讨论】:

嘿迈克尔,感谢您指出这个答案(不知何故错过了)。很高兴报告它有效,但必须使用bottomBarView 作为我的控制器视图的子视图并删除inputAccessoryView,因为它不是控制器视图的子视图,因此仍然没有考虑到按钮中的点击在它的框架之外。很高兴听到您是否有任何想法使其与inputAccessoryView 一起使用?

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

将 ImageView 锚定到折叠工具栏

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

导航栏可以锚定到特定位置吗?

如何将视图锚定到 android 软键盘

为啥锚定到 ApplicationWindow 的项目的大小为零?

如何将 Reality Composer (RealityKit) 场景锚定到检测到的图像