Как скрыть navigation bar на первом экране в Swift, но показывать на остальных?
Правильное решение: управление видимостью navigation bar в методах жизненного цикла
Проблема, которую вы описали, связана с тем, что viewDidLoad вызывается только один раз за время жизни контроллера. Когда вы возвращаетесь на первый экран, этот метод не вызывается снова, поэтому вы не управляете видимостью navigation bar в момент перехода. Решение — использовать методы viewWillAppear и viewWillDisappear, которые вызываются каждый раз, когда экран появляется или исчезает.
Основной подход: переопределение методов жизненного цикла
Вот правильная реализация для вашего случая:
class FirstViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Скрываем navigation bar при появлении первого экрана
navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Показываем navigation bar, когда уходим с первого экрана
navigationController?.setNavigationBarHidden(false, animated: animated)
}
}
class SecondViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Убеждаемся, что navigation bar виден на втором экране
navigationController?.setNavigationBarHidden(false, animated: animated)
}
}
Почему это работает
- Метод
viewWillAppear:вызывается каждый раз, когда экран становится видимым (включая возврат с другого экрана). - Метод
viewWillDisappear:вызывается перед тем, как экран исчезнет (например, при переходе на второй экран). - Параметр
animated: мы передаём его вsetNavigationBarHidden, чтобы анимация скрытия/показа была согласована с анимацией перехода между экранами. Это устраняет "моргание" и делает переход плавным.
Дополнительные советы
Если вы используете UINavigationController с root view controller, который должен быть всегда без navigation bar, а все дочерние — с bar, можно настроить это в самом navigation controller, делегируя логику:
class CustomNavigationController: UINavigationController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func navigationController(_ navigationController: UINavigationController,
willShow viewController: UIViewController,
animated: Bool) {
// Скрываем bar только для первого (root) контроллера
let isRoot = viewController == viewControllers.first
setNavigationBarHidden(isRoot, animated: animated)
}
}
Этот подход централизует логику и избавляет вас от необходимости писать код в каждом контроллере. Просто используйте CustomNavigationController в storyboard или при создании navigation controller программно.
Важные замечания
- Не используйте
viewDidLoadдля управления видимостью navigation bar, так как он вызывается один раз. - Всегда используйте
setNavigationBarHidden(_:animated:)вместо прямого присваиванияisHidden— это даёт плавную анимацию. - Если у вас есть жест свайпа назад (интерактивный pop), метод
viewWillAppearвсё равно будет вызван корректно, и анимация будет синхронизирована.
Альтернативный подход: использование UINavigationBarAppearance (iOS 13+)
Если вам нужно не просто скрыть, а сделать navigation bar прозрачным или полностью изменить его внешний вид, можно использовать UINavigationBarAppearance. Этот способ полезен, когда вы хотите сохранить место для status bar, но убрать визуальные элементы.
class FirstViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground() // Полностью прозрачный
appearance.shadowColor = .clear // Убираем тень/линию
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
navigationController?.navigationBar.isHidden = false // Bar остаётся, но невидим
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Восстанавливаем стандартный вид
let appearance = UINavigationBarAppearance()
appearance.configureWithDefaultBackground()
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
}
}
Когда это полезно
- Если на первом экране есть контент, который должен быть под status bar (например, полноэкранное изображение).
- Если вы хотите сохранить возможность нажатия на элементы в области navigation bar (например, кастомные кнопки).
- Если стандартное скрытие bar вызывает проблемы с layout (например, контент не поднимается вверх).
Этот способ более гибкий, но требует больше кода. Для простого скрытия/показа лучше использовать первый ответ.
Ответов пока нет.
Войдите чтобы оставить ответ