Сегодня встал в 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.
