Удалить 1px строку в верхней части UISearchController в больших заголовках UINavigationBar

Я перехожу из вида с большим стилем UINavigationItem в вид, который имеет большой стиль UINavigationItem и UISearchController, Я настроил цвет фона UINavigationBar,

По какой-то причине между 1 UINavigationBar и UISearchController, Я могу сказать, что это из NavigationBar, потому что, если я прокручиваю строку поиска до вершины, строка исчезает. Я просто не уверен, что генерирует эту линию. Я не использую тени или что-то необычное, кроме установки barTintColor и tintColor, Если я не использую большие названия стилей, я вижу линию, но только при переходе между представлениями. Это как при переходе UISearchController просто не прилипает к UINavigationBar,

Любая помощь в выяснении, откуда эта линия идет, приветствуется.

Обновление: По некоторым дальнейшим исследованиям, кажется, что это происходит только тогда, когда navigationItem.hidesSearchBarWhenScrolling установлен в false, Если он изначально скрыт, то анимация из предыдущего представления будет плавной, и показ полосы также будет плавным.

Пример скриншота строки

4 ответа

Решение

Тестируя элемент навигации и настройки панели поиска, которые вы описали, я мог воспроизводить только линию 1px/point во время анимации перехода.

Обходной путь: Эта строка на самом деле является фоновым представлением макета (forLastBaselineLayout) использован UINavigationBar в конечном итоге видимый из-за глючного обрамления UISearchBar, Установите его фон в соответствии с цветом панели навигации, чтобы скрыть его на заднем сайте.

// MARK: UINavigationControllerDelegate

public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
    viewController.navigationController?.navigationBar
        .forLastBaselineLayout.backgroundColor = .red // TODO:
}

Обязательно установите объект, реализующий UINavigationControllerDelegate устанавливается как navigationController.delegate чтобы получить вышеупомянутый вызов делегата.

Кроме того (не часть вопроса): UISearchBar Кажется, ведет себя странно при переходе (push и pop) между контроллерами, особенно когда есть / показать searchBar но не другой. Временное решение: визуально было приятнее временно скрыть панель поиска от представления контроллеров. Вот код, который я использую:

public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
    if let sender = navigationStack.popLast() {
        prepareSearchBarForTransition(from: sender)
    }
    navigationStack = navigationController.children
}

/// Set only from `navigationController: willShow`
private var navigationStack: [UIViewController] = []

func prepareSearchBarForTransition(from sender: UIViewController) {
    if #available(iOS 11.0, *) {
        let searchController = sender.navigationItem.searchController
        sender.navigationItem.searchController = nil
        weak var weakSender = sender
        let navigationTransitionDuration: TimeInterval = 0.33
        DispatchQueue.main.asyncAfter(deadline: .now() + navigationTransitionDuration) {
            /// Reset the search bar.
            weakSender?.navigationItem.searchController = searchController
        }
    } else {
        // TODO: Check if the above workaround is neccessary for < iOS 11
    }
}

Удалить одну пиксельную линию из всего приложения.

UINavigationBar.appearance().shadowImage = UIImage()

Выше кода удалите нижнюю строку из всего приложения. если хотите удалить только для некоторых определенных контроллеров, тогда требуется управлять скрытием / показом изображения нижней панели. Для этого используйте ниже UINavigationBar Расширение для управления скрытием показа нижней панели в одно пиксельное изображение.

extension UIView {

    fileprivate var hairlineImageView: UIImageView? {
        return hairlineImageView(in: self)
    }

    fileprivate func hairlineImageView(in view: UIView) -> UIImageView? {
        if let imageView = view as? UIImageView, imageView.bounds.height <= 1.0 {
            return imageView
        }

        for subview in view.subviews {
            if let imageView = self.hairlineImageView(in: subview) {
                return imageView
            }
        }
        return nil
    }
}

extension UINavigationBar {

    func hideBottomHairline() {
        self.hairlineImageView?.isHidden = true
    }

    func showBottomHairline() {
        self.hairlineImageView?.isHidden = false
    }
}

Чтобы управлять скрыть / показать

self.navigationController?.navigationBar.hideBottomHairline()

self.navigationController?.navigationBar.showBottomHairline()

Выше UIView расширение для hairlineImageView также может быть использован для других UIControls лайк UIToolBar

extension UIToolbar {

    func hideBottomHairline() {
        self.hairlineImageView?.isHidden = true
    }

    func showBottomHairline() {
        self.hairlineImageView?.isHidden = false
    }
}

Если вы хотите удалить строку 1px на UINavigationBar, во всем приложении вы можете использовать приведенный ниже код в AppDelegate (didFinishLaunchingWithOptions) (проверенный код)

UINavigationBar.appearance().shadowImage = UIImage()

Используйте следующий код:

navigationController?.navigationBar.shadowImage = UIImage()
Другие вопросы по тегам