Избегайте дрожания строки состояния iOS при переключении между страницами UIPageViewController - PullRequest
0 голосов
/ 16 декабря 2018

Я создаю простое приложение, которое использует UIPageViewController с двумя страницами.На одной странице я хочу показать строку состояния, а на другой - нет.Чтобы переход выглядел хорошо, я перемещаю строку состояния внутрь и наружу после того, как пользователь полностью заходит на страницу UIPageViewController , в зависимости от того, какая это страница.

Это нормально работаетустройства с корпусом датчика (выемка), такие как iPhone XR, но на устройствах с обычным экраном прямоугольной формы, таких как iPhone 8, выглядит очень глючно, например iPhone 8.

Пример iPhone XR - Высота панели навигации и содержание под ней остаются неизменными.

iPhone XR example GIF

Пример iPhone 8 - Когда строка состояния начинает анимироваться (скользить), содержимое скачет вверх, но затем возвращается к исходному положению, поскольку панель навигации оживляет вниз.

iPhone 8 example 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

Хотя в идеале я бы хотел избежать анимирования панели навигации с помощью строки состояния, как на экране iPhone XR, это гораздо более приятный опыт.Если у кого-то есть идеи о том, как сохранить панель навигации в том же месте, я все равно буду признателен за это.

1 Ответ

0 голосов
/ 17 декабря 2018

Я хотел бы рассмотреть возможность использования additionalSafeAreaInsets в вашем контроллере настроек, чтобы он всегда учитывал высоту строки состояния.Тогда вам, возможно, придется отключить его, когда вы представляете строку состояния (в этом нет уверенности на 100%).

...