最近在我们的项目中,使用customView的UIBarButtonItem出现问题。在iOS 11之前,我们通过灵活的间距项目进行了布局。这已不再适用,因此没有显示任何内容。
因为我在SO上找不到真正为我解决问题的答案,所以我调查了一下,并提出了一个我想与你分享的(无可置疑的hacky)解决方案。
也许它可以帮助您或您有一些反馈。这是混合的objc和swift代码,希望你不要介意。
答案 0 :(得分:10)
如WWDC视频Updating Your App for iOS 11所示:
"现在在iOS 11中,UI工具栏和UI导航栏都有 复杂且明确支持自动布局。"
所以我的第一步是在自定义视图本身上使用布局约束:
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customView];
[barButtonItem.customView.widthAnchor constraintEqualToConstant:375].active = YES;
[barButtonItem.customView.heightAnchor constraintEqualToConstant:44].active = YES;
这导致工具栏显示customView。问题在于视图的左右两侧存在差距。你可以看到它。 所以我查看了View Hierarchy Debugging工具并实现了,工具栏上有一个UIToolbarContentView。这个contentView有正确的大小(特别是宽度),我开始怀疑。我查看了contentView唯一的子视图,它是一个UIBarButtonStackView。这个stackView以某种方式限制了我的customView的宽度。
所以它看起来像这样:
contentView |<-fullWidth-------->|
stackView |<-reducedWidth->|
customView |<-reducedWidth->|
让我感到好奇的是,customView不是stackView的子视图。这可能是由于CustomView包含在UIBarButtonItem中的结果。 customView上的任何(附加)约束保持不变(或崩溃,因为视图不在同一层次结构中)。
在学习了所有这些之后,我在UIToolbar上添加了一个扩展名:
extension UIToolbar {
private var contentView: UIView? {
return subviews.find { (view) -> Bool in
let viewDescription = String(describing: type(of: view))
return viewDescription.contains("ContentView")
}
}
private var stackView: UIView? {
return contentView?.subviews.find { (view) -> Bool in
let viewDescription = String(describing: type(of: view))
return viewDescription.contains("ButtonBarStackView")
}
}
func fitContentViewToToolbar() {
guard let stackView = stackView, let contentView = contentView else { return }
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
}
}
它的作用是这样的:
它通过将名称与&#34; ContentView&#34;进行比较,从子视图中获取contentView。并通过在contentView上执行相同操作来获取stackView。
可能return subviews.first
会做同样的事,但我想确定。
然后设置布局约束并且瞧:它在全宽度下工作。
我希望有人可能觉得这很有用。如果有评论:我对这一点的反馈非常开放。也许我错过了一些东西,所有这一切都没有必要。
编辑:&#39;发现&#39; function是Sequence的扩展。它确实过滤了第一个&#39;看起来像这样:
extension Sequence {
func find(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> Self.Element? {
return try filter(isIncluded).first
}
}