IOS 11 предпочитает LargeTitles, не обновляющийся до прокрутки
Я реализовал базовый UIViewController с UITableView, который был завершен в UINavigationController. Я установил prefersLargeTitles
в true:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Coffees"
}
Тем не менее, заголовок остается маленьким, пока я не прокручу представление, после чего он увеличится. Я попытался перевести этот вызов туда, где я создаю UINavigationController, но эффекта не было. Я уверен, что navigationController не равен нулю, когда я устанавливаю prefersLargeTitles
.
Должен ли я обновлять это свойство в другом месте? Или мне нужно подать радар?
Update:
Это похоже на то, что если мой взгляд содержит UITableView
или сам является UITableViewController
Ответы
Ответ 1
У меня была та же проблема. Хотя вы не используете раскадровки, но я надеюсь, что это может помочь кому-то. Я проверил "Предпочитаю большие заголовки" для контроллера навигации (а не контроллера просмотра). Я встроил свой TableViewController. Все контроллеры просмотра после того, как контроллер навигации повернулся и имели большие заголовки, и он должен работать.
![]()
Ответ 2
У меня была такая же проблема только на одном представлении таблицы...
Мне пришлось установить:
self.tableView.contentInsetAdjustmentBehavior = .never
чтобы моя таблица перестала прокручиваться при загрузке uiviewcontroller.
Это автоматическая прокрутка таблицы, которая делает скрытый большой заголовок
Надеюсь, что это поможет
Ответ 3
Недавно я столкнулся с той же проблемой, и ни одно из предложений не помогло мне. Вместо этого все, что мне нужно было сделать, это вызвать sizeToFit()
. Образец кода:
private func configureNavigator() {
guard let navigationController = navigationController else { return }
navigationController.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .automatic
navigationController.navigationBar.sizeToFit()
}
Надеюсь, это поможет!
Ответ 4
Изменение contentInset tableView с помощью top:1
заставит NavigationBar развернуться и отобразить большие заголовки.
Obj-C,
-(void) viewWillAppear:(BOOL)animated {
if (@available(iOS 11.0, *)) {
tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0);
}
}
стриж
override func viewWillAppear(_ animated: Bool) {
if #available(iOS 11.0, *) {
tableView.contentInset = UIEdgeInsetsMake(1, 0, 0, 0)
}
}
Примечание. Если у вас есть tableView.reloadData()
в вашем viewWillAppear
обязательно вызовите его после редактирования contentInset
Ответ 5
В моем случае решение состояло в том, чтобы установить верхний выравнивание tableView в безопасную область, а не в Superview
Ответ 6
Я потратил на это значительное количество времени, поскольку сага prefersLargeTitle
работает на некоторых контроллерах представления, как и ожидалось, а с некоторыми выдает ту же проблему выше.
Решением для меня было отключить Расширенные края под верхними панелями в IB - для тех контроллеров представления, которые кратковременно показывают большой заголовок, пока содержимое табличного представления не загружено, тогда панель навигации возвращается к обычному размеру. Он показывает только большой заголовок при прокрутке табличного представления вниз.
Это обратно совместимо с iOS 10 и не оставляет пустого места над первой строкой в табличном представлении.
Я проверял prefersLargeTitle
в инспекторе атрибутов контроллеров навигации только в IB - ничего в коде. То же самое для largeTitleDisplayMode =.always
Что касается того, почему это происходит с некоторыми контроллерами представления, а не с другими, я понятия не имею!
Ответ 7
В раскадровке я установил элемент навигации Large Title
в Never
.
![Navigation Item]()
В моем методе ViewController viewDidLoad я устанавливал следующее:
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
Ответ 8
У меня была такая же проблема, и в моем случае оказалось, что структура раскадровки, работающая в iOS 10 с Swift 3 (а также работа с iOS 11 с Swift 3), вызывала проблему на iOS 11 с Swift 4.
Разработать:
У меня был обычный UIViewController в моей раскадровке, который я установил в подкласс UINavigationController (моя иерархия похожа на вашу, с подклассом UITabBarController → подкласс UINavigationController → подкласс UITableViewController).
В iOS 10 это работало нормально.
В iOS 11 это также отлично работает при запуске существующего приложения Swift 3.
Однако с приложением Swift 4, работающим на iOS 11, я видел те же самые симптомы, которые вы описали (большие заголовки появляются только при выводе/прокрутке представления вниз).
Чтобы исправить, я заменил элементы на основе UIViewController в раскадровке фактическими экземплярами UINavigationController (которые содержат UINavigationBar явно в раскадровке). У меня есть догадка, в которой возникает суть проблемы, поскольку экземпляры UIViewController didnt этот элемент явно объявлен в раскадровке).
Во всяком случае, это исправило проблему для меня.
Ill file radar, поскольку это похоже на регрессию Swift 4, так как для меня она работает как в iOS 10 с Swift 3, так и в iOS 11 с Swift 3.
Ответ 9
Я столкнулся с той же проблемой и обнаружил, что обычно лучше всего установить свойство prefersLargeTitles
из контроллера или объекта представления, который его устанавливает, и сделать это до его представления.
Например, если указанный диспетчер представлений отображается при запуске приложения:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
let someViewController: UIViewController = CustomViewController()
let theNavController = UINavigationController(rootViewController: someViewController)
theNavController.navigationBar.prefersLargeTitles = true
window.rootViewController = theNavController
window.makeKeyAndVisible()
return true
}
или при представлении определенного контроллера вида:
let someViewController: UIViewController = CustomViewController()
let theNavController = UINavigationController(rootViewController: someViewController)
theNavController.navigationBar.prefersLargeTitles = true
present(theNavController, animated: true, completion: nil)
Я нашел этот метод более надежным, чтобы гарантировать, что заголовок навигации отображается соответствующим образом. Надеюсь это поможет!:)
Ответ 10
Общее изменение поведения viewWillAppear(_:)
navigationBar
должно быть сделано в viewWillAppear(_:)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.prefersLargeTitles = true
}
После этого у меня все заработало.
Ответ 11
Я решил эту проблему через раскадровку
- Контроллер навигации → Панель навигации → Инспектор атрибутов → Предпочитает большие заголовки (отмечено)
- Контроллер представления → Элемент навигации → Инспектор атрибутов → Большой заголовок (автоматически или всегда отмечен)
Ответ 12
Программный:
- В AppDelegate.swift:
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let navigationController = UINavigationController.init(rootViewController: ViewController())
window?.rootViewController = navigationController
- В ViewController:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .automatic
}
override func loadView() {
super.loadView()
view.addSubview(tableView)
view.addSubview(loadingView)
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor),
tableView.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor)
])
}
Убедитесь, что ваш tableView
был ранее добавлен в ваш вид.
Ответ 13
Я думаю, что это выглядит немного глупо, но я эффективно решил проблему с этим:
self.navigationItem.prompt = ""
self.navigationItem.prompt = nil
Как и навигационный бар, для обновления макета требуется своего рода обновление одного из его элементов.
Иногда, чтобы обновить что-то в навигационной панели, мне нужно скрыть и показать это.. Вот почему я думаю, что есть лучший способ сделать это.. На данный момент мой обходной путь.
Ответ 14
Сначала это кажется странным поведением, но попробуйте установить navigationItem.largeTitleDisplayMode
на always
. Значение по умолчанию automatic
- и не определено, как это работает в docs.
Также написал/будет обновлять ответ о больших титрах здесь.
Ответ 15
У меня была аналогичная проблема. Представление представляет собой табличное представление. Свойство prefersLargeTitles
установлено в событии viewDidLoad
. Затем я установил заголовок представления в событии viewWillAppear
.
override open func viewDidLoad() {
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
} else {
// Fallback on earlier versions
}
...
}
override open func viewWillAppear(_ animated: Bool) {
self.navigationItem.title = "something"
...
}
В моем подготовительном событии segue я устанавливаю плиту элемента навигации на nil
, чтобы следующий вид в левой части навигационного элемента навигации автоматически отображался "Назад".
override func prepare(for segue: UIStoryboardSegue,
sender: Any?) {
self.navigationItem.title = nil
...
}
В первый раз, когда представление таблицы отображает большой заголовок правильно. Однако, если я выбираю строку для следующего представления и обратно в представление таблицы, заголовок пункта навигации становится пустым.
После нескольких часов борьбы я наконец узнал, что заголовок представления должен быть установлен в событии viewDidAppear
! Кажется, что все, что нужно для просмотра заголовка в событии Will
, было бы reset UIKit внутренне назад к нулю. Поэтому он должен быть установлен в другом событии.
override func viewDidAppear(_ animated: Bool) {
self.navigationItem.title = "something"
...
}
override open func viewWillAppear(_ animated: Bool) {
// self.navigationItem.title = "something" // Remove it and set title in Did event!
...
}
Прежде чем я представила эту новую функцию iOS 11, мое приложение работает нормально. Похоже, что новая функция имеет некоторые изменения в UIKit, поэтому для приложения предыдущей версии могут потребоваться некоторые обновления/изменения, чтобы заставить ее работать.
Ответ 16
У меня была такая же проблема и исправлена ее, изменив порядок просмотров в моем ViewController в InterfaceBuilder.
Кажется, что если первое представление в иерархии НЕ является ScrollView, тогда NavigationBar появляется в режиме LargeTitle и не анимируется вместе со списком прокрутки. Если вам нужно иметь заголовок панели навигации, чтобы отразить ваш прокрутка, вам нужно поместить свой вид прокрутки в качестве первой в иерархии.
Кроме того, я не совсем уверен в этом, но похоже, что отображение панели навигации в стандартном или режиме большого заголовка зависит от иерархии представлений предыдущего контроллера.
Ответ 17
Подобная проблема для меня с UITableViewController
добавленным в UIViewController
. В моем случае, эти контроллеры представления сами встроены в UITabBarController
и только первая отображаемая вкладка правильно использовала большой заголовок. Для других вкладок требовалась ручная прокрутка перед отображением большого заголовка.
Единственная вещь, которую я мог заставить работать, - это contentInset
согласно contentInset
@pau-senabre, за исключением того, что top
вставка мне не помогла. Вместо этого я устанавливаю left
вставку, а затем сбрасываю ее при следующем цикле выполнения.
private var isFirstAppearance = true
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if isFirstAppearance {
applyLargeTitlesFix()
}
}
private func applyLargeTitlesFix() {
let originalInset = tableViewController.tableView.contentInset
tableViewController.tableView.contentInset = UIEdgeInsets(top: 0, left: 1, bottom: 0, right: 0)
DispatchQueue.main.async { [weak self] in
self?.tableViewController.tableView.contentInset = originalInset
}
isFirstAppearance = false
}
Ответ 18
Попробуй это:
edgesForExtendedLayout = []
Ответ 19
Еще одно возможное решение - завершить обновление в refreshHandler(). как this-
@objc func refreshPage() {
self.refreshControl?.endRefreshing() //End here
self.loadTableData() //Get fresh data and reload table
}
Ответ 20
Та же проблема здесь с Swift 4.2, iOS 12 и переработанными раскадровками.
prefersLargeTitles = true
добавления prefersLargeTitles = true
для viewWillAppear
и viewDidLoad
, но ни одна из них не viewDidLoad
мою проблему.
Вместо этого я скопировал переработанные раскадровки обратно в main.storyboard и нашел возможность включить большие заголовки в IB. Установите эту опцию, затем измените раскадровки, и теперь все работает. По какой-то причине первоначальный рефакторинг убрал опцию, и я не смог включить ее программно.
Ответ 21
В моем случае это не сработало из-за navigationBarHidden
. Решение состоит в том, чтобы установить его в NO, прежде чем устанавливать prefersLargeTitles
.
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE", nil);
if (@available(iOS 11.0, *)) {
self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationBar.prefersLargeTitles = YES;
}
}
Ответ 22
У меня была похожая проблема с панелью навигации, но в моем случае у нее было настраиваемое представление заголовка, и панель навигации оставалась пустой до тех пор, пока просмотр таблицы не был прокручен вниз, что вызвало UILayoutContainerView
для размещения его подпредставлений, одним из которых является представление контроллера навигации и Панель навигации. Я предполагаю, что его корень совпадает с проблемой панели навигации большого заголовка.
Привязка tableView
к safeAreaLayoutGuide
не сработала для меня, largeTitleDisplayMode
не может быть другим, чем .never
Поэтому мне удалось это исправить, вызвав self.navigationController?.view.setNeedsUpdateConstraints
в представленной сверху функции контроллера viewDidAppear(animated:)
, или запланировав этот вызов для следующего цикла выполнения в viewWillAppear(animated:)
, например:
DispatchQueue.main.async {
self.navigationController?.view.setNeedsUpdateConstraints()
}
В этом случае панель навигации отображалась с правильным содержанием и размером вместе с представлением перехода, а не появлялась после завершения перехода