Ио 11 & картинки х: UINavigationBar's на панели инструментов интервалы неправильно врезанный в UITabBarController

Я испытываю досадная проблема тестирования новой iOS 11 на iPhone симулятор.

У меня есть UITabBarController и внутри каждой вкладки есть UINavigationController, каждый UINavigationBar определены также в нижней панели инструментов (setToolbarHidden:), и по умолчанию они появляются внизу, прямо над вкладками.

Он до сих пор работает нормально, и, кажется, работает нормально и в предстоящие iPhone 8 и 8 моделей плюс, но на iPhone Х есть промежуток между панелью инструментов и вкладками. Мое предположение заключается в том, что панели инструментов не'т понимаете, что будет отображаться в панели вкладок, а затем покидает вмещающее пространство внизу.

Я думаю, единственный способ отремонтировать его будет использовать пользовательскую панель инструментов и дисплей/анимировать сам вместо того, чтобы использовать UINavigationBar по умолчанию, но хотелось бы услышать другие варианты :)

  • Вот как это выглядит на iPhone 8.
  • А вот это проблема на iPhone Х.

Комментарии к вопросу (13)
Решение

Я подал это как radr://проблемы/34421298, который был закрыт, так как является дубликатом проблемы radr:///34462371. Однако, в последней бета-версии Xcode версии 9.2 (9C32c) с iOS 11.2, это, кажется, быть исправлены. Здесь'ы пример мое приложение работает в симуляторе каждого устройства, без каких-либо изменений между ними.

Это'т действительно решение проблемы, кроме того, что немного терпения, возможно, решить ее без необходимости прибегать к ИП хитрости. Мое предположение, что iOS 11.2 будет до конца года, поскольку она'ы, необходимые для поддержки HomePod.

Комментарии (0)

Если вы Don'т считаю оборотов можно попробовать манипулировать слой панели как очень замысловато, но быстрое решение.

class FixNavigationController: UINavigationController
{
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        updateTollbarPosition()
    }

    func updateTollbarPosition() {
        guard let tabbarFrame = tabBarController?.tabBar.frame else {
            return
        }
        let gapHeight = tabbarFrame.origin.y-toolbar.frame.origin.y-toolbar.frame.size.height

        var
        frame = toolbar.layer.frame
        frame.origin.y += gapHeight

        toolbar.layer.frame = frame
    }    
}

К сожалению, анимации не'т выглядеть хорошо, когда дело доходит до такого подхода. В таком случае, добавление пользовательской панели инструментов вместо стандартного будет лучшим решением.

Комментарии (0)

выпустила iOS 11.1 и iPhone Х и этот баг/особенность, это'т еще. Так я реализовал этот метод. Этот код работает в iOS 9.0+.

Просто установите этот класс В вашей раскадровке, как навигационный контроллер'S-класса. Он будет использовать пользовательскую панель инструментов в iPhone X с правильной ограничения макета, и возвращается к родным в другие устройства. Пользовательская панель инструментов добавляется к навигации контроллер's посмотреть, а не ваш контроллер представления, чтобы сделать переходы более плавными.

  • Важное примечание: вы должны позвонить updateItems(анимированный:) вручную после установки toolbarItems вашего контроллера представления, чтобы обновить интерфейс. Если вы установитеtoolbarItems` собственность навигационный контроллер, вы можете игнорировать этот шаг.

Он имитирует все родное панели инструментов поведения (включая изменение высоты панели в портретном/ландшафтном режимах), кроме пуш/поп-анимации.

import UIKit

class FixNavigationController: UINavigationController {

    private weak var alterToolbarHeightConstraint: NSLayoutConstraint?

    private var _alterToolbar: UIToolbar?

    private func initAlretToolbar() {
        _alterToolbar = UIToolbar()
        _alterToolbar!.isTranslucent = true
        _alterToolbar!.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(_alterToolbar!)
        if view.traitCollection.verticalSizeClass == .compact {
            alterToolbarHeightConstraint = _alterToolbar!.heightAnchor.constraint(equalToConstant: 32.0)
        } else {
            alterToolbarHeightConstraint = _alterToolbar!.heightAnchor.constraint(equalToConstant: 44.0)
        }
        let bottomAnchor: NSLayoutConstraint
        if #available(iOS 11.0, *) {
            bottomAnchor = _alterToolbar!.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        } else {
            bottomAnchor = _alterToolbar!.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor)
        }
        NSLayoutConstraint.activate([
            _alterToolbar!.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            _alterToolbar!.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            bottomAnchor,
            alterToolbarHeightConstraint!
            ])
        self.view.updateFocusIfNeeded()
        self.view.layoutIfNeeded()
    }

    private var alterToolbarInSuper: UIToolbar? {
        var superNavigationController = self.navigationController as? FixNavigationController
        while superNavigationController != nil {
            if superNavigationController?._alterToolbar != nil {
                return superNavigationController?._alterToolbar
            }
            superNavigationController = superNavigationController?.navigationController as? FixNavigationController
        }
        return nil
    }

    private var alterToolbar: UIToolbar! {
        get {
            if let t = alterToolbarInSuper {
                return t
            }
            if _alterToolbar == nil {
                initAlretToolbar()
            }
            return _alterToolbar
        }
    }

    // This is the logic to determine should use custom toolbar or fallback to native one
    private var shouldUseAlterToolbar: Bool {
        // return true if height is iPhone X's one
        return UIScreen.main.nativeBounds.height == 2436
    }

    /// Manually call it after setting toolbar items in child view controllers
    func updateItems(animated: Bool = false) {
        if shouldUseAlterToolbar {
            (_alterToolbar ?? alterToolbarInSuper)?.setItems(viewControllers.last?.toolbarItems ?? toolbarItems, animated: animated)
        }
    }

    override var isToolbarHidden: Bool {
        get {
            if shouldUseAlterToolbar {
                return _alterToolbar == nil && alterToolbarInSuper == nil
            } else {
                return super.isToolbarHidden
            }
        }
        set {
            if shouldUseAlterToolbar {
                if newValue {
                    super.isToolbarHidden = newValue
                    _alterToolbar?.removeFromSuperview()
                    _alterToolbar = nil
                    self.view.updateFocusIfNeeded()
                    self.view.layoutIfNeeded()
                    // TODO: Animation when push/pop
                    alterToolbarHeightConstraint = nil
                    var superNavigationController = self.navigationController as? FixNavigationController
                    while let superNC = superNavigationController {
                        if superNC._alterToolbar != nil {
                            superNC._alterToolbar?.removeFromSuperview()
                            superNC._alterToolbar = nil
                            superNC.view.updateFocusIfNeeded()
                            superNC.view.layoutIfNeeded()
                        }
                        superNavigationController = superNC.navigationController as? FixNavigationController
                    }
                } else {
                    alterToolbar.setItems(viewControllers.last?.toolbarItems ?? toolbarItems, animated: false)
                }
            } else {
                super.isToolbarHidden = newValue
            }
        }
    }

    override func setToolbarItems(_ toolbarItems: [UIBarButtonItem]?, animated: Bool) {
        super.setToolbarItems(toolbarItems, animated: animated)
        updateItems(animated: animated)
    }

    override var toolbarItems: [UIBarButtonItem]? {
        get {
            return super.toolbarItems
        }
        set {
            super.toolbarItems = newValue
            updateItems()
        }
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        guard let _alterToolbar = _alterToolbar else {
            return
        }
        self.alterToolbarHeightConstraint?.isActive = false
        let height: CGFloat = (view.traitCollection.verticalSizeClass == .compact) ? 32.0 : 44.0
        let alterToolbarHeightConstraint = _alterToolbar.heightAnchor.constraint(equalToConstant: height)
        alterToolbarHeightConstraint.isActive = true
        self.alterToolbarHeightConstraint = alterToolbarHeightConstraint
    }
}
Комментарии (0)

Я нашел только одно решение: добавить панель инструментов непосредственно к контроллеру вид

Комментарии (1)

Apple до сих пор еще не исправили этот баг в iOS 11.2. Происходит от Хусейн мусавиан'ы решение, вот простой подход, который я взял.

Я взял этот подход, потому что у меня только один UITableViewController, где эта ошибка происходит. Так что в моем случае, я просто добавил следующий код, перечисленных ниже, чтобы мой файл ViewController (который является UITableViewController), где эта ошибка происходит.

Преимущества:

  • Это исправление происходит в случае с iPhone X. нет побочных эффектов ожидать на других устройствах
  • Работает с любым переходом
  • Работает независимо от другого родителя/контроллеры ребенка, имеющего тулбаров или нет
  • Простой

И вот код:

1.Добавить startFixIPhoneXToolbarBug в свой viewWillAppear как это:

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

    startFixIPhoneXToolbarBug()
}

2.Добавить endFixIPhoneXToolbarBug в свой viewWillDisappear как это:

override func viewWillDisappear(_ animated: Bool)
{
    super.viewWillDisappear(animated)

    endFixIPhoneXToolbarBug()
}

3.Реализации пуск/endFixIPhoneXToolbarBug в файле ViewController как это:

private var alterToolbarHeightConstraint: NSLayoutConstraint? = nil
private var alterToolbar: UIToolbar? = nil

func startFixIPhoneXToolbarBug()
{
    // Check if we are running on an iPhone X
    if UIScreen.main.nativeBounds.height != 2436
    {
        return  // No
    }
    // See if we have a Toolbar
    if let tb:UIToolbar = self.navigationController?.toolbar
    {
        // See if we already added our own
        if alterToolbar == nil
        {
            // Should always be the case
            if let tbView = tb.superview
            {
                // Create a new Toolbar and apply correct constraints
                alterToolbar = UIToolbar()
                alterToolbar!.isTranslucent = true
                alterToolbar!.translatesAutoresizingMaskIntoConstraints = false
                tb.isHidden = true
                tbView.addSubview(alterToolbar!)
                if tbView.traitCollection.verticalSizeClass == .compact
                {
                    alterToolbarHeightConstraint = alterToolbar!.heightAnchor.constraint(equalToConstant: 32.0)
                }
                else
                {
                    alterToolbarHeightConstraint = alterToolbar!.heightAnchor.constraint(equalToConstant: 44.0)
                }
                let bottomAnchor: NSLayoutConstraint
                if #available(iOS 11.0, *)
                {
                    bottomAnchor = alterToolbar!.bottomAnchor.constraint(equalTo: tbView.safeAreaLayoutGuide.bottomAnchor)
                }
                else
                {
                    bottomAnchor = alterToolbar!.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor)
                }
                NSLayoutConstraint.activate([
                    alterToolbar!.leadingAnchor.constraint(equalTo: tbView.leadingAnchor),
                    alterToolbar!.trailingAnchor.constraint(equalTo: tbView.trailingAnchor),
                    bottomAnchor,
                    alterToolbarHeightConstraint!
                    ])
                tbView.updateFocusIfNeeded()
                tbView.layoutIfNeeded()
            }
        }
        // Add the original items to the new toolbox
        alterToolbar!.setItems(tb.items, animated: false)
    }
}

func endFixIPhoneXToolbarBug()
{
    if alterToolbar != nil
    {
        alterToolbar!.removeFromSuperview()
        alterToolbar = nil
        alterToolbarHeightConstraint = nil

        if let tb:UIToolbar = self.navigationController?.toolbar
        {
            tb.isHidden = false
        }
    }
}
Комментарии (0)