Comment supprimer la bordure de la navigationBar dans Swift?


131

J'ai essayé de supprimer la bordure navigationBars sans chance. J'ai fait des recherches et les gens semblent dire de définir shadowImage et BackgroundImage sur nil, mais cela ne fonctionne pas dans mon cas.

Mon code

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

illustration:

entrez la description de l'image ici

Réponses:


309

Le problème vient de ces deux lignes:

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

Comme vous n'avez pas d'image sans nom, UIImage(named: "")renvoie nil, ce qui signifie que le comportement par défaut entre en jeu:

Lorsqu'il n'est pas nul, une image d'ombre personnalisée à afficher à la place de l'image d'ombre par défaut. Pour qu'une ombre personnalisée soit affichée, une image d'arrière-plan personnalisée doit également être définie avec -setBackgroundImage: forBarMetrics: (si l'image d'arrière-plan par défaut est utilisée, l'image d'ombre par défaut sera utilisée).

Vous avez besoin d'une image vraiment vide, alors initialisez simplement avec UIImage():

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

2
Cette réponse fonctionne vraiment. Parce que si vous utilisez la réponse acceptée (code), il supprime l'imageViews de la barre d'outils.
Sergey Krasiuk

1
Cela devrait être la réponse acceptée. Fonctionne également lors du réglage de UINavigationBar.appearance ()
Heinrisch

1
Cela devrait être la réponse acceptée pour Swift 3. La réponse acceptée a fonctionné pour moi dans Swift 2, mais pas dans Swift 3
ColinMasters

1
pour le swift3, vous devez écrire de manière légèrement différente: self.navigationController? .navigationBar.setBackgroundImage (UIImage (), pour: UIBarMetrics.default) self.navigationController? .navigationBar.shadowImage = UIImage ()
Chetan Dobariya

5
Cette méthode est en conflit avec le grand titre dans iOS 11
SteffenK

53

Swift 4 et Swift 5

Suppression de la bordure:

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

Restauration de la bordure:

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

2
Réponse parfaite :)
PJR

Avons-nous besoin de layoutIfNeeded () ici?
korgx9

1
Oui korgx9, nous en avons besoin. Sinon, la couleur ne changera pas avant le prochain tirage.
Sazzad Hissain Khan

37

cela supprimera complètement l'image d'ombre

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

1
Pourriez-vous élaborer?
Kmeixner le

1
Cette solution fonctionne également pour moi, alors que la réponse de @Nate Cook ne fonctionne pas. : S
Luca Davanzo

2
Saint sheist !! Après toutes ces recherches, c'est la SEULE chose qui a fonctionné.
Tuan Anh Vu

cela fonctionne, mais j'ai aussi une icône de menu dans la barre de navigation et elle a disparu: / je veux juste que la bordure soit effacée. AIDE: /
Stephy Samaniego

Cela a fonctionné pour moi, mais après avoir poussé le nouveau ViewController, il supprime la ligne de là à. Comment puis-je l'empêcher?
Anirudha Mahale

36

Avec Swift 2, vous pouvez le faire de cette façon:

Fichier AppDelegate

Dans l'application func (..., didFinishLaunchingWithOptions launchOptions: ...)

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

pour Swift 3:

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

Bonne réponse.
Ed.

C'est la réponse complète!
madeny le

Mieux vaut écrire ces valeurs par défaut utiles sur Appdelegate que de les écrire aux endroits impairs. Bonne réponse :)
Md Rais

35

Écrivez simplement ceci dans l'extension de UINavigationBar

extension UINavigationBar {

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

Et dans votre vueController ...

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

Et pour annuler cette opération pour n'importe quel viewController, transmettez simplement false.


Cela fonctionne très bien MAIS cela se cache si pour TOUS les vcs sur la pile de navigation. Si vous l'utilisez dans vc1 et que vc1 peut pousser vers vc2, il sera également masqué sur vc2. Pour afficher l'ombre dans vc2, vous devrez le définir sur false dans viewDidLoad. Le problème est que lorsque vous revenez à vc1, il s'affiche à nouveau car il a été réinitialisé dans vc2. Vous devez utiliser la logique pour aller et venir, ce qui pourrait ne pas en valoir la peine. Cependant, si vous ne voulez pas du tout que l'image d'ombre apparaisse sur les vcs, c'est le moyen le plus simple
Lance Samaria

Disons que nous avons une pile de viewControllers avec 5 viewControllers (et nous avons caché l'ombre dans le premier). Maintenant, pour le 3ème viewController uniquement, je ne veux PAS cacher l'ombre. Donc, j'appellerai cette méthode avec FALSE dans viewWillAppear et avec TRUE in viewWillDisparaît du 3e viewController. C'est tout ce qu'il faut!
Gaurav Chandarana

votre tout à fait correct, bonne pensée! Ne pensez pas que j'ai frappé votre réponse parce qu'elle est très succincte et efficace, je l'ai également votée. Je l'utilise pour le supprimer et la barre de navigation pour les messages d'erreur. Le problème que j'ai trouvé était lors de la suppression dans vc1 mais en le montrant vc2, mais s'il y avait une erreur dans vc2, le supprimer dans viewWillDisappear pourrait ne pas fonctionner. Mais encore une fois, c'est une situation tout à fait unique. J'aime l'idée de viewWillDisappear pour une utilisation générale et vous devriez l'ajouter à votre réponse. Peu importe que votre code fonctionne et c'est un moyen facile de supprimer l'ombre! 👍🏿👍🏿
Lance Samaria

Fonctionne comme un charme. Vous voulez juste vous assurer qu'il ne s'agit pas de paramètres privés?
inokey

2
C'est une excellente réponse! J'ai ajouté une réponse qui simplifie le code.
Scott Gardner

13

Réglez barStylesur .Blackavant de régler la teinte:

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

est-ce un peu aléatoire que cela fonctionne réellement? ou est-ce que je réfléchis trop?
joe

@joe bien ça marche ici :-) ça ne marche pas pour toi?
gpbl

c'est la chose, ça fonctionne. Je me demande juste s'il y a une explication à la raison pour laquelle tourner le barStyle en noir, il transforme alors toute la barreTintColor en bleu :)
joe

peut-être en le définissant sur noir et opaque, cela désactive certains calques / vues dans la
barre de

J'ai essayé de l'utiliser, et cela supprime la ligne du bas, mais si vous utilisez une teinte de barre de blanc, le titre n'est pas visible: /
RileyDev

11

Swift 5

Lorsque vous utilisez setBackgroundImage / shadowImage pour masquer la racine des cheveux, il y a un léger retard. Cette méthode supprime le délai. Crédit à Chameleon Framework . C'est la méthode qu'ils utilisent (dans 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, c'est la seule solution qui a fonctionné pour moi sur iOS 13.4 ...
kevinstueber

9

La réponse de Luca Davanzo est excellente, mais elle ne fonctionne pas sous iOS 10. Je l'ai modifiée pour qu'elle fonctionne sous iOS 10 et inférieur.

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
            }
        }
    }
}

Vous pouvez également étendre UINavigationController et appeler cela hors de cela. removeFromSuperview()sur la ligne ne fonctionnera pas sur iOS 10, je viens donc de définir l'alpha sur 0 pour que cet appel soit compatible partout.


Belle prise, un moyen d'afficher / masquer l'ombre dans certains contrôleurs de vue pendant la navigation?
Ashkan.H

Vous devriez plutôt vérifier les hauteurs qui ont un height >= 1.0. Sur les modèles d'iPhone dotés d'un écran rétine 3x (par exemple 8 Plus, XR ...), la racine des cheveux a une hauteur de 0,33.
fl034

7

Pour supprimer la bordure de UINavigationBar dans Swift 3+, utilisez:

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

5

pour swift 3

dans la viewDidLoadméthode

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


4

Mise à jour pour Swift 4 au cas où quelqu'un se demanderait

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

C'est encore moins bavard maintenant.


2

Voici comment procéder si vous souhaitez le faire sans changer la couleur d'arrière-plan:

// 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()
        }
    }
}

REMARQUE: cela peut se bloquer sur une application de production. Apparemment, la NavigationBar n'aime pas que sa vue disparaisse


2

La réponse acceptée a fonctionné pour moi, mais j'ai remarqué que lorsque je voulais que l'image d'ombre réapparaisse lors du retour ou de la poussée vers un autre vc, il y avait un clignotement notable dans la barre de navigation.

En utilisant cette méthode navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") dans viewWillAppear, la barre d'ombre est masquée dans le contrôleur de vue visible actuel.

Utiliser ces 2 méthodes

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

dans viewWillDisappear, le clignotement se produit toujours, mais uniquement lorsque l'image d'ombre réapparaît et non la barre de navigation elle-même.

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

pour le swift3, vous devez écrire de manière légèrement différente:

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

1

Ceci est une version simplifiée de la réponse de Gaurav Chandarana .

extension UINavigationBar {

    func hideShadow(_ value: Bool = true) {
        setValue(value, forKey: "hidesShadow")
    }
}

1

Délégué d'application

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

1

Si vous souhaitez supprimer uniquement la ligne du bas et conserver la couleur unie de navigationBar, ajoutez ces lignes de code dans viewDidLoad: Swift 3, 4:

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

Paix!


0

La ligne de bordure est une UIImageView et la suppression d'une sous-vue qui est une imageView supprimera barButtonItems avec UIImageView. Le code ci-dessous vous aidera à le supprimer. J'espère que cela aide quelqu'un qui a fait face à un problème comme moi.

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

La bordure UIImageView ne mesure que 0,5 de hauteur, ce code ne supprime donc que cela.


Cela m'a causé des plantages. Je pense que parent et childViews doivent être déballés au cas où ils seraient nuls avant de vérifier chacun d'eux. J'utilise cependant un UINavigationController personnalisé, donc ce n'est peut-être pas le cas pour les autres utilisateurs avec une barre standard.
Natalia

0

Dans AppDelegate , cela a globalement changé le format de la NavBar et supprime la ligne / bordure du bas:

 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()] }

Je n'ai pas réussi à mettre en œuvre quoi que ce soit de différent sur un VC spécifique, mais cela aidera 90% des personnes


UINavigationBar.appearance (). BackgroundColor = UIColor.redColor () n'est pas nécessaire.
sabiland

0

c'est la réponse dans la base rapide 3 de la réponse de Nate Cook

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

0

iOS 11 et Swift 4 Vous devriez essayer de suivre si vous souhaitez supprimer la bordure mais ne pas rendre la barre de navigation translucide
self.navigationBar.shadowImage = UIImage()


0

dans votre navigation personnaliséeController ajoutez ces lignes:

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

Note importante

la dernière ligne est importante si vous utilisez la méthode viewDidLoad () de première ligne car navigationController doit redessiner la barre de navigation, mais vous pouvez facilement l'utiliser sans layoutIfNeeded () dans la méthode viewWillAppear () avant de dessiner la barre de navigation


0

Méthode plus rapide de Jack Chen:

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
    }
}

En utilisant:

    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()
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.