UINavigationBar使用弹性空间均匀分布条形按钮项
UINavigationBar using flexible spaces to distribute bar button items evenly
在基于 UINavigationController 的应用程序中,导航控制器的工具栏已打开,因此顶部有 UINavigationBar,底部有 UIToolbar。
对于根视图控制器,显然没有后退按钮,也没有标题(也没有标题视图)。我设置了 title = nil
.
同一个根视图控制器在导航栏 rightBarButtonItems
中有很多栏按钮项。由于除了这些项目之外导航栏中没有其他内容,我希望它们在导航栏中居中并均匀 spaced。这样,它们看起来不那么拥挤,不太可能触错按钮,总体上看起来更漂亮,并且也与底部工具栏的外观相匹配。
在底部工具栏中,这可以通过在每个项目之间使用灵活的 space 轻松实现(在我的例子中 before/after first/last 项目)。
对于顶部导航栏,灵活的 spaces(和固定的 spaces)似乎被忽略了。
当栏上没有其他内容时,如何让导航栏中的栏按钮项目分布在整个栏中?
或者是隐藏栏的唯一选项,实际上在顶部放置一个独立的工具栏? (不得不求助于此将是一种耻辱,因为导航栏已经存在并且几乎可以完成工作并且是自动管理的。)
以下是我如何完成在导航栏中使用灵活的 spaces 来均匀地 space 出所有栏按钮项目的近似方法。
注意:就目前而言,它仅适用于带有图像的栏按钮项目。纯文本项目不起作用,因为它使用图像大小来确定项目的宽度。更新它以使用文本或 text/image 项应该不会太难。
它的工作原理是将所有条形按钮项目中所有图像的总宽度相加,然后从条形的大小中减去它以获得剩余的 space 量。然后将其除以项目数(加一,因为我想要在所有项目前后添加 space)并调整屏幕比例。
将此设置为新固定 space 项目的宽度。
重新添加这些项目,在每个项目之前、之间和之后添加新的 space。
func updateNavbarItemSpacing(forBarWidth width: CGFloat) {
guard let oldItems = navigationItem.leftBarButtonItems else { return }
var nonSpaceItems: [UIBarButtonItem] = []
var usedWidth: CGFloat = 0.0
var itemCount:CGFloat = 0.0
for item in oldItems {
if let itemWidth = item.image?.size.width {
usedWidth += itemWidth
itemCount += 1
nonSpaceItems.append(item)
}
}
let spaceWidth = ( ( width - usedWidth) / itemCount + 1 ) / UIScreen.main.scale
let fixedSpace = UIBarButtonItem.fixedSpace(spaceWidth)
var newItems: Array<UIBarButtonItem> = [fixedSpace]
for item in nonSpaceItems {
newItems.append(item)
newItems.append(fixedSpace)
}
navigationItem.leftBarButtonItems = newItems
}
每当项目更新时,以及导航栏大小发生变化时,都应调用此函数。例如,不要忘记将它包含在视图控制器中:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateNavbarItemSpacing(forBarWidth: size.width)
}
目前在测试中运行良好。完美的肖像模式。但是在 lasdcape 方向上,我最后得到了一些额外的 space。尚未弄清楚这一点。
我现在找到了一种更简单的方法来实现这一目标。
此版本简单地将可用 space 分配给项目数。
减去 2 点似乎效果更好 - 如果没有这个,结果在拥挤的工具栏中就不那么令人满意了。我想这允许每个项目之间留出很小的余量?
请注意,如果某些项目的 text/image 比其他项目宽,则每个项目之间的间距将不均匀。所以这种方法最适合宽度相近的物品。
func updateNavbarItemSpacing(forBarWidth barWidth: CGFloat) {
guard let items = navigationItem.leftBarButtonItems else { return }
if items.count == 0 { return }
let itemWidth = barWidth / CGFloat(items.count) - 2
for item in items {
item.width = itemWidth
}
navigationItem.leftBarButtonItems = items
}
设置navigationItem的左toobar项后调用上面的方法。
此外,为了在旋转设备时获得正确的行为,请在视图控制器中调用它:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateNavbarItemSpacing(forBarWidth: size.width)
}
在基于 UINavigationController 的应用程序中,导航控制器的工具栏已打开,因此顶部有 UINavigationBar,底部有 UIToolbar。
对于根视图控制器,显然没有后退按钮,也没有标题(也没有标题视图)。我设置了 title = nil
.
同一个根视图控制器在导航栏 rightBarButtonItems
中有很多栏按钮项。由于除了这些项目之外导航栏中没有其他内容,我希望它们在导航栏中居中并均匀 spaced。这样,它们看起来不那么拥挤,不太可能触错按钮,总体上看起来更漂亮,并且也与底部工具栏的外观相匹配。
在底部工具栏中,这可以通过在每个项目之间使用灵活的 space 轻松实现(在我的例子中 before/after first/last 项目)。
对于顶部导航栏,灵活的 spaces(和固定的 spaces)似乎被忽略了。
当栏上没有其他内容时,如何让导航栏中的栏按钮项目分布在整个栏中?
或者是隐藏栏的唯一选项,实际上在顶部放置一个独立的工具栏? (不得不求助于此将是一种耻辱,因为导航栏已经存在并且几乎可以完成工作并且是自动管理的。)
以下是我如何完成在导航栏中使用灵活的 spaces 来均匀地 space 出所有栏按钮项目的近似方法。
注意:就目前而言,它仅适用于带有图像的栏按钮项目。纯文本项目不起作用,因为它使用图像大小来确定项目的宽度。更新它以使用文本或 text/image 项应该不会太难。
它的工作原理是将所有条形按钮项目中所有图像的总宽度相加,然后从条形的大小中减去它以获得剩余的 space 量。然后将其除以项目数(加一,因为我想要在所有项目前后添加 space)并调整屏幕比例。
将此设置为新固定 space 项目的宽度。
重新添加这些项目,在每个项目之前、之间和之后添加新的 space。
func updateNavbarItemSpacing(forBarWidth width: CGFloat) {
guard let oldItems = navigationItem.leftBarButtonItems else { return }
var nonSpaceItems: [UIBarButtonItem] = []
var usedWidth: CGFloat = 0.0
var itemCount:CGFloat = 0.0
for item in oldItems {
if let itemWidth = item.image?.size.width {
usedWidth += itemWidth
itemCount += 1
nonSpaceItems.append(item)
}
}
let spaceWidth = ( ( width - usedWidth) / itemCount + 1 ) / UIScreen.main.scale
let fixedSpace = UIBarButtonItem.fixedSpace(spaceWidth)
var newItems: Array<UIBarButtonItem> = [fixedSpace]
for item in nonSpaceItems {
newItems.append(item)
newItems.append(fixedSpace)
}
navigationItem.leftBarButtonItems = newItems
}
每当项目更新时,以及导航栏大小发生变化时,都应调用此函数。例如,不要忘记将它包含在视图控制器中:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateNavbarItemSpacing(forBarWidth: size.width)
}
目前在测试中运行良好。完美的肖像模式。但是在 lasdcape 方向上,我最后得到了一些额外的 space。尚未弄清楚这一点。
我现在找到了一种更简单的方法来实现这一目标。
此版本简单地将可用 space 分配给项目数。
减去 2 点似乎效果更好 - 如果没有这个,结果在拥挤的工具栏中就不那么令人满意了。我想这允许每个项目之间留出很小的余量?
请注意,如果某些项目的 text/image 比其他项目宽,则每个项目之间的间距将不均匀。所以这种方法最适合宽度相近的物品。
func updateNavbarItemSpacing(forBarWidth barWidth: CGFloat) {
guard let items = navigationItem.leftBarButtonItems else { return }
if items.count == 0 { return }
let itemWidth = barWidth / CGFloat(items.count) - 2
for item in items {
item.width = itemWidth
}
navigationItem.leftBarButtonItems = items
}
设置navigationItem的左toobar项后调用上面的方法。
此外,为了在旋转设备时获得正确的行为,请在视图控制器中调用它:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateNavbarItemSpacing(forBarWidth: size.width)
}