Evgenii 3000 Profile picture
iOS dev since 2008 🍏 ex-Head of Mobile📱 ex-Engineering Manager 👮🏽‍♂️ ex-Twitter user ✍️

May 10, 2020, 13 tweets

Сегодня встал в 5:30 🙃, и к 10 утра уже успел отлично и продуктивно покодить 👍.

Раньше я уже писал про large titles в UINavigationBar, сегодня окончательно их освоил. Поискал в каких приложениях (кроме системных) они ещё используются и нашёл только Тинькова.

Сделано у них очень криво (@tinkoff_bank без обид 🙃). Либо свои контролы с имитацией нативного поведения, либо неправильное использование UIKit.

Если кто не понял 🙃, то проблемы хорошо видны при медленном интерактивном swipeToBack (про висящую поверх всех окон иконку профиля я молчу 😁).

Давайте за образец возьмём анимацию в системных приложениях Apple, например "Настройки".

Посмотрел ещё SO, он просто пестрит запросами "fix large titles animation", "large titles glitch", "enable large titles"...

Люди изобретают фантастические велосипеды 😵morningswiftui.com/blog/fix-large…

Дальше будет небольшой гайдик как сделать плавный переход с системной анимацией и отсутствием глитчей при swipeToBack на примере нативного UINavigationController и 2-х UIViewController-aх, первый из которых должен показывать large titles, а второй нет.

Давайте вспомним базу🙃:

1. UINavigationController содержит UINavigationBar
2. UIViewController имеет UINavigationItem
3. При вызове push у UINavigationController в UINavigationBar анимированно добавляется UINavigationItem следующего контроллера

Ещё один важный и очень простой моментик:

При обращении к свойству navigationController внутри UIViewController, вы изменяете ОБЩИЙ навигационный контроллер!

Теперь go.

Первым делом нужно задать свойство prefersLargeTitles у UINavigationBar в true, и больше его никогда не трогать!

Никаких изменений prefersLargeTitles в viewWillAppear и viewWillDisapear – это сразу сломает всю анимацию, плюс, рано или поздно вы сломаете свой UINavigationBar.

Дальше у первого контроллера нужно установить navigationItem.largeTitleDisplayMode = .always, а у второго .never. Сделать это нужно ДО вызова viewDidLoad. Я делаю это в Storyboard.

Не нужно никаких двойных переустановок свойства как часто советуют на SO: stackoverflow.com/questions/4637…

На этот момент у вас всё верно собрано. Но, посмотрев на анимацию swipeToBack, мы можем увидеть что навигационный бар зарезает наш контент!

Кажется что это баг, но это фича 🙃.

UINavigationBar принадлежит UINavigationController, на первом контроллере у нас оставался "увеличенный" навигационный бар, а на втором – "компактный". UINavigationController решает увеличить фрейм бара при анимации, мы не можем его винить!

Видимо здесь все и сдавались 😁

Решение на поверхности. Посмотрите на цвета: оранжевый – это navigationBar.backgroundColor, а зелёный – navigationBar.barTintColor.

Теперь делаем navigationBar.backgroundColor = .clear и получаем под ним цвет view первого UIViewController-а.

Всё готово, больше ничего не нужно.

Смотрите ещё раз на анимацию 🐸. Можете поделиться и сделать мир iOS-ных приложений чуть более UIKit-каноничным 🍏✅.

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling