锚定到 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 的按钮仅在其框架中工作的主要内容,如果未能解决你的问题,请参考以下文章
如何将 UIAlertController 操作表锚定到特定单元格 UICollectionView?