使用大型导航标题时如何使视图居中?

How can I centre a view when using a large nav title?

我有一个搜索视图控制器,我想在屏幕中央显示一个加载指示器,但由于我使用的是大标题导航,它似乎有偏移但大导航的高度?

我怎样才能偏移它,使其位于屏幕的真正中心?

我正在使用

设置它
      tableView.addSubview(searchingView)
      searchingView.translatesAutoresizingMaskIntoConstraints = false
      NSLayoutConstraint.activate([
        searchingView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor),
        searchingView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor)
      ])

我的视图控制器在下面

final class SearchViewController: UITableViewController {

  private var searchLoadingController: SearchLoadingController?
  private var searchController: UISearchController?

  convenience init(searchLoadingController: SearchLoadingController, searchController: UISearchController) {
    self.init(nibName: nil, bundle: nil)
    self.searchLoadingController = searchLoadingController
    self.searchController = searchController
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    configureUI()
  }

}

extension SearchViewController: UISearchResultsUpdating {
  func updateSearchResults(for searchController: UISearchController) {
    guard let text = searchController.searchBar.text, !text.isEmpty else { return }
    searchLoadingController?.search(query: text)
  }
}

extension SearchViewController: SearchErrorView {
  func display(_ viewModel: SearchErrorViewModel) { }
}


private extension SearchViewController {
  func configureUI() {
    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.searchController = searchController

    tableView.tableFooterView = UIView(frame: .zero)

    searchController?.searchBar.searchBarStyle = .minimal
    searchController?.searchResultsUpdater = self
    searchController?.obscuresBackgroundDuringPresentation = false

    if let searchingView = searchLoadingController?.view {
      tableView.addSubview(searchingView)
      searchingView.translatesAutoresizingMaskIntoConstraints = false
      NSLayoutConstraint.activate([
        searchingView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor),
        searchingView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor)
      ])
    }

  }
}

如果您真的想要屏幕中央的activity指标,您需要做一些计算:

func addActivityIndicatorToCenterOfScreen() {
    let screenHeight = UIScreen.main.bounds.size.height
    let activityIndicatorHeight = searchingView.bounds.size.height
    let safeAreaBottomInset = tableView.safeAreaInsets.bottom
    let yOffset = (screenHeight - activityIndicatorHeight) / 2 - safeAreaBottomInset

    tableView.addSubview(searchingView)
    searchingView.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
        searchingView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor),
        searchingView.bottomAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.bottomAnchor, constant: -yOffset),
    ])
}

还要确保在布局视图后配置约束。 viewDidAppear 是一个很好的地方。这是必要的,因为我们需要知道tableView的大小和安全区域。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    addActivityIndicatorToCenterOfScreen()
}

现在进行一些解释。 tableView.safeAreaLayoutGuide 包括导航栏和屏幕底部槽口之间的 tableView 部分。 tableView.safeAreaInsets.bottom 给出了屏幕底部凹口的高度。 yOffset 是屏幕中心减去 activity 指标高度的一半减去屏幕底部缺口的高度。我们将从安全区域的底部偏移 activity 指标的底部。这会将 activity 指示器的中心置于屏幕的中心。

如果我是你,我会将 activity 指示器置于导航栏和刘海顶部之间的中心位置。它更干净,您可以在 viewDidLoad:

中执行此操作
func addActivityIndicatorCenteredBetweenNavBarAndSafeAreaBottom() {
    tableView.addSubview(searchingView)
    searchingView.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
        searchingView.centerXAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.centerXAnchor),
        searchingView.centerYAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.centerYAnchor),
    ])
}