Я создаю простое приложение, которое использует UIPageViewController с двумя страницами.На одной странице я хочу показать строку состояния, а на другой - нет.Чтобы переход выглядел хорошо, я перемещаю строку состояния внутрь и наружу после того, как пользователь полностью заходит на страницу UIPageViewController , в зависимости от того, какая это страница.
Это нормально работаетустройства с корпусом датчика (выемка), такие как iPhone XR, но на устройствах с обычным экраном прямоугольной формы, таких как iPhone 8, выглядит очень глючно, например iPhone 8.
Пример iPhone XR - Высота панели навигации и содержание под ней остаются неизменными.
![iPhone XR example GIF](https://i.stack.imgur.com/SjDnh.gif)
Пример iPhone 8 - Когда строка состояния начинает анимироваться (скользить), содержимое скачет вверх, но затем возвращается к исходному положению, поскольку панель навигации оживляет вниз.
![iPhone 8 example GIF](https://i.stack.imgur.com/yyVqe.gif)
Наилучшее возможное решение?
Похоже, что одним из лучших решений было бы как-то заставить панель навигации всегда быть на всю высоту панели навигации + статусвысота бара, поэтому навигация баr и содержимое остаются на одном месте, а строка состояния анимируется вниз.Это было бы похоже на поведение на экране iPhone XR.Как мне этого добиться?
Существующий код
На моем UIPageViewController я отслеживаю currentViewController атрибута и обновите переопределенную prefersStatusBarHidden соответственно.
private var currentViewController: UIViewController?
override var prefersStatusBarHidden: Bool {
if let current = currentViewController,
current == settingsNavigationController {
return false
} else {
return true
}
}
Чтобы установить переменную currentViewController и вызвать необходимую setNeedsStatusBarAppearanceUpdate () метод, я переопределяю didFinishAnimating метод UIPageViewControllerDelegate :
extension PageViewController: UIPageViewControllerDelegate {
func pageViewController(_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
currentViewController = pageViewController.viewControllers?.first
UIView.animate(withDuration: 0.2) { () -> Void in
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
Чтобы сделать его менее резким, я использую анимацию .slide (если я оставлю это без анимации, то на прямоугольных экранах она все еще будет нервной):
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
ОБНОВЛЕНИЕ:
Благодаря ЛеонОтвет Дериглазова . Мне удалось избежать скачкообразности контента, создав подкласс UINavigationController
.Я добавил следующий код для запуска анимации (с такой же продолжительностью, что и анимация строки состояния), которая перемещает содержимое вверх, а строка состояния перемещается вниз, в результате чего содержимое остается на том же месте:
class SettingsNavigationController: UINavigationController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.2) {
self.additionalSafeAreaInsets.top = 0
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
additionalSafeAreaInsets.top = 20
}
}
Примечание: здесь нет дополнительной логики, необходимой для определения типа устройства.
Вот как это выглядит:
![fixed jitter](https://i.stack.imgur.com/9XTJa.gif)
Хотя в идеале я бы хотел избежать анимирования панели навигации с помощью строки состояния, как на экране iPhone XR, это гораздо более приятный опыт.Если у кого-то есть идеи о том, как сохранить панель навигации в том же месте, я все равно буду признателен за это.