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

Я решил эту проблему через раскадровку

  1. Контроллер навигации → Панель навигации → Инспектор атрибутов → Предпочитает большие заголовки (отмечено)
  2. Контроллер представления → Элемент навигации → Инспектор атрибутов → Большой заголовок (автоматически или всегда отмечен)

Ответ 12

Программный:

  1. В AppDelegate.swift:
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.makeKeyAndVisible()

        let navigationController = UINavigationController.init(rootViewController: ViewController())
        window?.rootViewController = navigationController
  1. В 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()
}

В этом случае панель навигации отображалась с правильным содержанием и размером вместе с представлением перехода, а не появлялась после завершения перехода