自定义 UIToolbar 太靠近 iPhone X 上的 home 指示器

问题描述 投票:0回答:4

我有一个自定义的

UIToolbar
,当标签栏隐藏时我会显示它。 iPhone X 上的工具栏按钮离主页指示器太近:

let toolbar = UIToolbar()
let height = tabBarController?.tabBar.frame.height
toolbar.frame = CGRect(x: 0, y: view.bounds.height - height, width: view.bounds.width, height: height)
toolbar.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
view.addSubview(toolbar)

按钮距离主页指示器太近

这就是我想要的样子(邮件应用程序)^

由于这是一个自定义视图,我知道我可以更改 y 位置并将其移动到从安全区域的底部开始,但我宁愿移动按钮。我使用的是普通的

UIBarButtonItem
,中间有灵活的空间。

ios swift iphone-x
4个回答
8
投票

iOS 11
中,Apple 弃用了
top and bottom layout guides
,并替换为单个
safe area layout guide
。 因此,请使用
Safe Area Layout Guides
将视图从主页指示器移至上方。

使用故事板:

  • 转到
    Storyboard
    并在
    Interface Builder Document section
  • 勾选
    Use Safe Area Layout Guides
    复选框
  • 然后将
    Bottom Constraint
    更改为相对于
    Safe Area

现在视图已在

Home Indicator
上方对齐。

或通过编码,

   toolbar.translatesAutoresizingMaskIntoConstraints = false

   NSLayoutConstraint.activate([
        toolbar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
        toolbar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
        toolbar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
        toolbar.heightAnchor.constraint(equalToConstant: 50)
        ])

请参阅本文了解相对于安全区域定位内容


6
投票

您不需要设置明确的高度或大小即可使其工作,只需利用

layoutMarginsGuide
UIBarPositioningDelegate
采用的
UIToolbarDelegate
协议即可。 首先,布局工具栏,使其固定在视图的layoutMarginsGuide 的底部。

let constraints = [
    toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    toolbar.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)

这将使工具栏与 iOS 11+ 设备上的安全区域对齐,但您需要做最后一件事才能让工具栏将其背景一直延伸到视图底部。要使其简单地符合类中的

UIToolbarDelegate
,请将自己设置为工具栏的委托,实现函数
position(for: UIBarPositioning) -> UIBarPosition
,并返回值
.bottom
。 UIToolbar 的 barPosition 的默认值是底部,因此在大多数用例中可能不需要最后一步。 完成此操作后,您应该看到工具栏相对于安全区域布置其项目,同时将背景一直延伸到视图底部,就像您在 Mail 和 Safari 中看到的那样。

在这种情况下,使用layoutMarginsGuide而不是safeAreaLayoutGuide的优点在于,layoutMarginsGuide默认将布局边距插入安全区域。因为您不直接引用安全区域,所以您的代码可以一直向后兼容 iOS 9,而无需使用可用性检查。


3
投票

我也遇到了这个问题。我的解决方案是使用通用 UIView 来占底部

safeAreaInset
,然后将工具栏添加为该视图的子视图。

private func addToolbar(_ toolbar: UIToolbar, toView view: UIView) {
    toolbar.frame = CGRect(
        x: 0,
        y: 0,
        width: view.frame.size.width,
        height: 0
    )
    toolbar.sizeToFit() // This sets the standard height for the toolbar.

    // Create a view to contain the toolbar:
    let toolbarParent = UIView()
    toolbarParent.frame = CGRect(
        x: 0,
        y: view.frame.size.height - toolbar.frame.size.height,
        width: toolbar.frame.size.width,
        height: toolbar.frame.size.height
    )

    // Adjust the position and height of the toolbar's parent view to account for safe area:
    if #available(iOS 11, *) {
        toolbarParent.frame.origin.y -= view.safeAreaInsets.bottom
        toolbarParent.frame.size.height += view.safeAreaInsets.bottom
    }

    toolbarParent.addSubview(toolbar)
    view.addSubview(toolbarParent)
}

0
投票

Apple 的应用程序,如邮件、提醒、日历,它们使用 UIViewController.setToolbarItems(_:animated:)

let navigationController: UINavigationController = .init(rootViewController: ViewController())
navigationController.setToolbarHidden(false, animated: false)

@MainActor final class ViewController: UIViewControlle {
    override func viewDidLoad() {
        setToolbarItems([.init(image: .init(systemName: "camera.aperture"), style: .plain, target: self, action: #selector(foo(_:)))], animated: false)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.