如WWDC视频所示将您的应用程序更新为 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;
这导致工具栏显示自定义视图。问题是,视野的左右有一个间隙。你可以看到它。
于是我查看了View Hierarchy Debugging工具,发现工具栏上有一个UIToolbarContentView。这个 contentView 有正确的尺寸(尤其是宽度),我开始想知道。我查看了 contentView 唯一的子视图,它是一个 UIBarButtonStackView。这个 stackView 在宽度方面以某种方式限制了我的 customView 。
所以它看起来像这样:
contentView |<-fullWidth-------->|
stackView |<-reducedWidth->|
customView |<-reducedWidth->|
让我好奇的是,customView 不是 stackView 的子视图。这可能是 UIBarButtonItem 中包含 customView 的结果。对 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
}
}
那么它的作用是这样的:
它通过将名称与“ContentView”进行比较来从子视图中获取 contentView,并通过对 contentView 执行相同的操作来获取 stackView。
大概是一个return subviews.first
也会做同样的事情,但我想确定一下。
然后设置布局约束,瞧:它在全宽度下工作。
我希望有人会觉得这很有用。如果有评论:我非常愿意接受对此的反馈。也许我错过了一些东西,而这一切根本没有必要。
编辑:“查找”功能是序列的扩展。它执行“filter.first”,如下所示:
extension Sequence {
func find(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> Self.Element? {
return try filter(isIncluded).first
}
}