在使用 LargeTitle 和带有 table 视图的分段控件时遇到问题
Having trouble with LargeTitle and a segmented control with a table view
可以在 https://github.com/SRowley90/LargeTitleIssueTestiOS
找到示例项目
我试图在 iOS 应用程序中将分段控件放置在大标题下方。我有一个包含分段控件的 UIToolbar。
向上滚动时 title
和 toolbar
的行为符合预期。
向下滚动导航栏时是正确的,但它不会将 UITabBar 或 UITableView 向下推,这意味着标题位于分段控件上方,如下图所示。
我很确定这与我设置的约束有关,但我不知道是什么。
- TabBar 固定在顶部、左侧和右侧。
- TableView 固定在底部、左侧和右侧。
- tableView垂直固定在TabBar上
我设置了位置 UITabBarDelegate 方法:
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
把tableView
的委托带到某处:
tableView.delegate = self
覆盖 scrollViewDidScroll
并更新 toolbar
位置外观(因为真实位置不应根据具有良好的弹跳效果而改变。
extension ViewController: UIScrollViewDelegate {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
var verticalOffset = scrollView.contentOffset.y + defaultNavigationBarHeight
if scrollView.refreshControl?.isRefreshing ?? false {
verticalOffset += 60 // After is refreshing changes its value the toolbar goes 60 points down
print(toolbar.frame.origin.y)
}
if verticalOffset >= 0 {
toolbar.transform = .identity
} else {
toolbar.transform = CGAffineTransform(translationX: 0, y: -verticalOffset)
}
}
}
您可以在应用转换之前使用以下检查,使默认 iOS 样式更加可靠和自然:
if #available(iOS 11.0, *) {
guard let navigationController = navigationController else { return }
guard navigationController.navigationBar.prefersLargeTitles else { return }
guard navigationController.navigationItem.largeTitleDisplayMode != .never else { return }
}
对我来说,使用 UIScrollViewDelegate
与 CollectionView 和工具栏配合使用效果不佳。所以,我做了:
final class CollectionViewController: UICollectionViewController {
private var observesBag: [NSKeyValueObservation] = []
private let toolbar = UIToolbar()
override func viewDidLoad() {
super.viewDidLoad()
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let navigationBarHeight = navigationController?.navigationBar.frame.height ?? 0
let defaultNavigationBarHeight = statusBarHeight + navigationBarHeight
let observation = navigationController!
.navigationBar
.observe(\.center, options: NSKeyValueObservingOptions.new) { [weak self] navBar, _ in
guard let self = self else { return }
let newNavigatonBarHeight = navBar.frame.height + statusBarHeight
let yTranslantion = newNavigatonBarHeight - defaultNavigationBarHeight
if yTranslantion > 0 {
self.toolbar.transform = CGAffineTransform(
translationX: 0,
y: yTranslantion
)
} else {
self.toolbar.transform = .identity
}
}
observesBag.append(observation)
}
}
观察 navigationBar
的 "center" 是否有变化,然后翻译 y-axis 中的 toolbar
。
尽管当我尝试将此解决方案与 UIRefreshControl
和大标题一起使用时效果很好,但效果不佳。
我将刷新控件设置为:
private func setupRefreshControl() {
let refreshControl = UIRefreshControl()
self.webView.scrollView.refreshControl = refreshControl
}
UINavigationBar
的高度在完全刷新触发后改变。
可以在 https://github.com/SRowley90/LargeTitleIssueTestiOS
找到示例项目我试图在 iOS 应用程序中将分段控件放置在大标题下方。我有一个包含分段控件的 UIToolbar。
向上滚动时 title
和 toolbar
的行为符合预期。
向下滚动导航栏时是正确的,但它不会将 UITabBar 或 UITableView 向下推,这意味着标题位于分段控件上方,如下图所示。
我很确定这与我设置的约束有关,但我不知道是什么。
- TabBar 固定在顶部、左侧和右侧。
- TableView 固定在底部、左侧和右侧。
- tableView垂直固定在TabBar上
我设置了位置 UITabBarDelegate 方法:
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
把tableView
的委托带到某处:
tableView.delegate = self
覆盖 scrollViewDidScroll
并更新 toolbar
位置外观(因为真实位置不应根据具有良好的弹跳效果而改变。
extension ViewController: UIScrollViewDelegate {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
var verticalOffset = scrollView.contentOffset.y + defaultNavigationBarHeight
if scrollView.refreshControl?.isRefreshing ?? false {
verticalOffset += 60 // After is refreshing changes its value the toolbar goes 60 points down
print(toolbar.frame.origin.y)
}
if verticalOffset >= 0 {
toolbar.transform = .identity
} else {
toolbar.transform = CGAffineTransform(translationX: 0, y: -verticalOffset)
}
}
}
您可以在应用转换之前使用以下检查,使默认 iOS 样式更加可靠和自然:
if #available(iOS 11.0, *) {
guard let navigationController = navigationController else { return }
guard navigationController.navigationBar.prefersLargeTitles else { return }
guard navigationController.navigationItem.largeTitleDisplayMode != .never else { return }
}
对我来说,使用 UIScrollViewDelegate
与 CollectionView 和工具栏配合使用效果不佳。所以,我做了:
final class CollectionViewController: UICollectionViewController {
private var observesBag: [NSKeyValueObservation] = []
private let toolbar = UIToolbar()
override func viewDidLoad() {
super.viewDidLoad()
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let navigationBarHeight = navigationController?.navigationBar.frame.height ?? 0
let defaultNavigationBarHeight = statusBarHeight + navigationBarHeight
let observation = navigationController!
.navigationBar
.observe(\.center, options: NSKeyValueObservingOptions.new) { [weak self] navBar, _ in
guard let self = self else { return }
let newNavigatonBarHeight = navBar.frame.height + statusBarHeight
let yTranslantion = newNavigatonBarHeight - defaultNavigationBarHeight
if yTranslantion > 0 {
self.toolbar.transform = CGAffineTransform(
translationX: 0,
y: yTranslantion
)
} else {
self.toolbar.transform = .identity
}
}
observesBag.append(observation)
}
}
观察 navigationBar
的 "center" 是否有变化,然后翻译 y-axis 中的 toolbar
。
尽管当我尝试将此解决方案与 UIRefreshControl
和大标题一起使用时效果很好,但效果不佳。
我将刷新控件设置为:
private func setupRefreshControl() {
let refreshControl = UIRefreshControl()
self.webView.scrollView.refreshControl = refreshControl
}
UINavigationBar
的高度在完全刷新触发后改变。