Як швидко видалити кордон навігаційного бару?


131

я намагався без удачі видалити кордон навігації. Я досліджував, і люди, здається, говорять, щоб встановити shadowImage та BackgroundImage на нуль, але це не працює в моєму випадку.

Мій код

    self.navigationController?.navigationBar.barTintColor = UIColor(rgba: "#4a5866")
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
    self.navigationController?.navigationBar.shadowImage = UIImage(named: "")

ілюстрація:

введіть тут опис зображення

Відповіді:


309

Проблема полягає в цих двох рядках:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage(named: "")

Оскільки у вас немає зображення без імені, UIImage(named: "")повертається nil, що означає, що поведінка за замовчуванням починається:

Якщо це не-нульове, зображення власного тіні для показу замість тіньового зображення за замовчуванням Для відображення користувацької тіні також слід встановити спеціальне фонове зображення за допомогою -setBackgroundImage: forBarMetrics: (якщо використовується фонове зображення за замовчуванням, буде використано тіньове зображення за замовчуванням).

Вам потрібно справді порожнє зображення, тому просто ініціалізуйте UIImage():

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()

2
Ця відповідь справді працює. Тому що якщо використовується прийнята відповідь (код), її видалити imageViews на панелі інструментів.
Сергій Красюк

1
Це має бути прийнятою відповіддю. Також працює під час встановлення з UINavigationBar.appearance ()
Heinrisch

1
Це має бути прийнята відповідь для Swift 3. Прийнята відповідь працювала для мене в Swift 2, але не в Swift 3
ColinMasters

1
для swift3 слід написати дещо інший спосіб: self.navigationController? .navigationBar.setBackgroundImage (UIImage (), для: UIBarMetrics.default) self.navigationController? .navigationBar.shadowImage = UIImage ()
Четан Dobariya 14

5
Цей метод суперечить великому заголовку в iOS 11
SteffenK

53

Swift 4 та Swift 5

Видалення кордону:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.layoutIfNeeded()

Відновлення кордону:

self.navigationController?.navigationBar.setBackgroundImage(nil, for:.default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.layoutIfNeeded()

2
Ідеальна відповідь :)
PJR

Чи потрібна тут layoutIfNeeded ()?
korgx9

1
Так korgx9, нам це потрібно. Інакше він не буде змінювати колір до наступного розіграшу.
Sazzad Hissain Khan

37

це повністю видалить тіньове зображення

for parent in self.navigationController!.navigationBar.subviews {
 for childView in parent.subviews {
     if(childView is UIImageView) {
         childView.removeFromSuperview()
     }
 }
}

1
Не могли б ви детальніше?
Kmeixner

1
Також для мене працює це рішення, поки відповідь @Nate Cook не працює. : S
Лука Даванцо

2
Святий шейст !! Зрештою, це пошук ТІЛЬКИ, що спрацювало.
Tuan Anh Vu

він працює, але також у мене є значок меню на панелі навігації, і він зник: / я просто хочу, щоб межа була стерта. ДОПОМОГА: /
Stephy Samaniego

Це працювало для мене, але після натискання нового ViewController він видаляє лінію звідти. Як я можу запобігти цьому?
Анірудха Махале

36

З Swift 2 ви можете це зробити так:

Файл AppDelegate

Всередині функціональної програми (..., didFinishLaunchingWithOptions запускOptions: ...)

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarMetrics: .Default)

для Swift 3:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)

Правильна відповідь.
Ред.

Це вичерпна відповідь!
madeny

Краще писати такі корисні за замовчуванням в Appdelegate, ніж писати їх у непарних місцях. Правильна відповідь :)
Md Rais

35

Просто напишіть це у розширенні UINavigationBar

extension UINavigationBar {

    func shouldRemoveShadow(_ value: Bool) -> Void {
        if value {
            self.setValue(true, forKey: "hidesShadow")
        } else {
            self.setValue(false, forKey: "hidesShadow")
        }
    }
}

І на ваш погляд, контролер ...

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.shouldRemoveShadow(true)        
}

І щоб скасувати цю дію для будь-якого переглядуController, просто передайте помилку.


Це чудово працює, Але він ховається, якщо для ВСІХ ПК на nav стеці. Якщо ви використовуєте його в vc1 і vc1 може натиснути на vc2, він також буде прихований і на vc2. Щоб показати тінь у vc2, вам доведеться встановити значення false у viewDidLoad. Проблема полягає в тому, що коли ви повернетесь до vc1, він знову з’явиться, оскільки він був скинутий у vc2. Ви повинні використовувати логіку, щоб повертатися вперед і назад, що може не варто. Однак якщо ви взагалі не хочете, щоб тіньові зображення відображалися на будь-яких Vcs, тоді це найпростіший спосіб
Lance Samaria

Скажімо, у нас є стек viewControllers з 5 viewControllers (І ми приховали тінь у першому). Тепер лише для 3-го виду viewController, я НЕ "хочу приховати тінь. Отже, я називаю цей метод FALSE у viewWillAppear та з TRUE у viewWillDisappear of 3rd viewController. Це все, що потрібно!
Gaurav Chandarana,

ваше абсолютно правильне, гарне мислення! Не думаю, що я вибив вашу відповідь, оскільки це дуже лаконічно і ефективно, я також проголосував за це. Я використовую його для видалення та navBar для повідомлень про помилки. Я знайшов проблему, коли видаляв її в vc1, але показував її vc2, але якщо виникла помилка vc2, то видалення її в viewWillDisappear може не працювати. Але знову-таки це дуже унікальна ситуація. Мені подобається ідея viewWillDisappear для загального використання випадків, і ви повинні додати її до своєї відповіді. Незалежно від того, ваш код працює, і це простий спосіб видалити тінь! 👍🏿👍🏿
Ленс Самарія

Працює як шарм. Просто хотіли переконатися, що це не приватні налаштування?
inokey

2
Це відмінна відповідь! Я додав відповідь, яка упорядковує код.
Скотт Гарднер

13

Встановіть barStyleна .Blackперед установкою відтінку:

self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()

Це якось випадково, що це насправді працює? чи я переосмислюю?
Джо

@joe добре, це працює тут :-) це не працює для вас?
gpbl

у цьому річ, це ВИНАГАЄ. Мені просто цікаво, чи є пояснення, чому перетворити барStyle на чорний він перетворює весь барTintColor на синій :)
joe

можливо, встановивши його на чорний і непрозорий, він вимикає деякі шари / перегляд у навігаційному
барі

Я спробував використовувати це, і він видаляє
підсумок,

11

Швидкий 5

Використовуючи setBackgroundImage / shadowImage для приховування лінії волосся, є невелика затримка. Цей спосіб знімає затримку. Кредит Хамелеонові Рамки . Це метод, який вони використовують (в ObjC)


extension UINavigationController {
    func hideHairline() {
        if let hairline = findHairlineImageViewUnder(navigationBar) {
            hairline.isHidden = true
        }
    }
    func restoreHairline() {
        if let hairline = findHairlineImageViewUnder(navigationBar) {
            hairline.isHidden = false
        }
    }
    func findHairlineImageViewUnder(_ view: UIView) -> UIImageView? {
        if view is UIImageView && view.bounds.size.height <= 1.0 {
            return view as? UIImageView
        }
        for subview in view.subviews {
            if let imageView = self.findHairlineImageViewUnder(subview) {
                return imageView
            }
        }
        return nil
    }
}

1
FWIW, це єдине рішення, яке працювало для мене на iOS 13.4 ...
kevinstueber

9

Відповідь Лука Даванзо чудова, але вона не працює в iOS 10. Я змінив її для роботи в iOS 10 і нижче.

for parent in navigationController!.view.subviews {
    for child in parent.subviews {
        for view in child.subviews { 
            if view is UIImageView && view.frame.height == 0.5 {
                view.alpha = 0
            }
        }
    }
}

Ви також можете продовжити UINavigationController і відкликати це. removeFromSuperview()на лінії не буде працювати на iOS 10, тому я просто встановив альфа на 0, щоб цей один дзвінок був сумісний скрізь.


Хороший улов, будь-який спосіб показати / приховати тінь у якомусь представленні контролерів під час навігації?
Ashkan.H

Ви повинні скоріше перевірити, чи немає висоти height >= 1.0. На моделях iPhone з 3-кратним екраном сітківки (наприклад, 8 Plus, XR ...) лінія волосся має висоту 0,33.
fl034

7

Щоб видалити кордон з UINavigationBar у Swift 3+, використовуйте:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
UINavigationBar.appearance().isTranslucent = false

5

для швидкого 3

у viewDidLoadметоді

navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()


4

Оновлено для Swift 4, якщо хтось цікавиться

navigationBar.shadowImage = UIImage()
navigationBar.backIndicatorImage = UIImage()

Зараз це ще менш багатослівно.


2

Це так, якщо ви хочете зробити це, не змінюючи колір фону:

// Remove the border ImageView from the NavigationBar background
func hideBottomBorder() {
    for view in navigationBar.subviews.filter({ NSStringFromClass($0.dynamicType) == "_UINavigationBarBackground" }) as [UIView] {
        if let imageView = view.subviews.filter({ $0 is UIImageView }).first as? UIImageView {
            imageView.removeFromSuperview()
        }
    }
}

ПРИМІТКА. Це може призвести до збоїв у виробництві. Мабуть, NavigationBar не любить, як його погляд зникає


2

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

Використовуючи цей метод navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") у viewWillAppear, тіньова смужка прихована у поточному контролері видимого перегляду.

Використовуючи ці 2 методи

navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")

в viewWillDisappear миготіння все-таки трапляється, але лише тоді, коли тіньове зображення з’являється знову, а не сама навігаційна панель.

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

    // 1. hide the shadow image in the current view controller you want it hidden in
    navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
    navigationController?.navigationBar.layoutIfNeeded()
}

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

    // 2. show the shadow image when pushing or popping in the next view controller. Only the shadow image will blink
    navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
    navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")
    navigationController?.navigationBar.layoutIfNeeded()
}

1

для swift3 слід написати трохи інакше:

 self.navigationController?.navigationBar.setBackgroundImage(UIImage(),
    for: UIBarMetrics.default)
   self.navigationController?.navigationBar.shadowImage = UIImage()


1

Делегат програми

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()

1

Якщо ви хочете видалити лише нижній рядок і зберегти суцільний колір навігаційного бар, додайте ці рядки коду у viewDidLoad: Swift 3, 4:

navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = false

Мир!


0

Лінія кордону - це UIImageView, і видалення підвідного перегляду, який є imageView, видалить barButtonItems з UIImageView. Нижче код допоможе вам його видалити. Сподіваюся, це допомагає тому, хто стикався з такою проблемою, як я.

for parent in self.navigationController!.navigationBar.subviews {
        for childView in parent.subviews {
            if childView.frame.height == 0.5 {
                childView.removeFromSuperview()
            }
        }
    }

Висота кордону UIImageView - лише 0,5, тому цей код видаляє лише це.


Це спричинило збої для мене. Я думаю, що батьків та childViews потрібно розгортати на випадок, якщо вони нульові, перш ніж перевірити кожен. Я використовую користувальницький UINavigationController, тому, можливо, це не стосується інших користувачів зі стандартною панеллю.
Наталія

0

У AppDelegate це глобально змінило формат NavBar і видалило нижню лінію / межу:

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarPosition: UIBarPosition.Any, barMetrics: UIBarMetrics.Default)
    UINavigationBar.appearance().shadowImage = UIImage()
    UINavigationBar.appearance().tintColor = UIColor.whiteColor()
    UINavigationBar.appearance().barTintColor = UIColor.redColor()
    UINavigationBar.appearance().translucent = false
    UINavigationBar.appearance().clipsToBounds = false
    //UINavigationBar.appearance().backgroundColor = UIColor.redColor()
    UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : (UIFont(name: "FONT NAME", size: 18))!, NSForegroundColorAttributeName: UIColor.whiteColor()] }

Не вдалося реалізувати щось інше на певному ВК, але це допоможе 90% людей


UINavigationBar.appearance (). BackgroundColor = UIColor.redColor () не потрібен.
sabiland

0

це відповідь у швидкій 3 базі відповіді Нейт Кука

   self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    self.navigationController?.navigationBar.shadowImage = UIImage()

0

iOS 11 та Swift 4 Спробуйте виконати наступні дії, якщо ви хочете видалити рамку, але не робите навігаційну панель напівпрозорою.
self.navigationBar.shadowImage = UIImage()


0

у ваші користувацькі навігаційні контролери додайте ці рядки:

self.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.layoutIfNeeded()

Важлива примітка

останній рядок важливий, якщо ви використовуєте метод viewDidLoad () першого рядка, тому що navigationController повинен перекроювати панель навігації, але легко ви можете використовувати це без layoutIfNeeded () у методі viewWillAppear () перед тим, як намалювати панель nav


0

Швидкий метод Джека Чена:

extension UINavigationController {

    var isHiddenHairline: Bool {
        get {
            guard let hairline = findHairlineImageViewUnder(navigationBar) else { return true }
            return hairline.isHidden
        }
        set {
            if let hairline = findHairlineImageViewUnder(navigationBar) {
                hairline.isHidden = newValue
            }
        }
    }

    private func findHairlineImageViewUnder(_ view: UIView) -> UIImageView? {
        if view is UIImageView && view.bounds.size.height <= 1.0 {
            return view as? UIImageView
        }

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

        return nil
    }
}

Використання:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.isHiddenHairline = true
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isHiddenHairline = false
    }

0
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.