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

Peter Pik
la source

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()
Nate Cook
la source
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()
Sazzad Hissain Khan
la source
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()
     }
 }
}
Steve Payne
la source
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)
Jorge Casariego
la source
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.

Gaurav Chandarana
la source
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()
gpbl
la source
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
    }
}
Jack Chen
la source
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.

David Baez
la source
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
reza_khalafi
la source
5

pour swift 3

dans la viewDidLoadméthode

navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
Gulz
la source
4

Seulement cela a fonctionné pour moi,

self.navigationController?.navigationBar.shadowImage = UIImage()

Réf

Mohammad Zaid Pathan
la source
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.

Mauricio Chirino
la source
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

Yariv Nissim
la source
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()
}
Lance Samaria
la source
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()
Chetan Dobariya
la source
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")
    }
}
Scott Gardner
la source
1

Délégué d'application

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
CSE 1994
la source
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!

Mihail Salari
la source
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.

Bachman
la source
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

David West
la source
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()
Alan
la source
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()

BilalReffas
la source
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

Monsieur Zee
la source
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
    }
Mickael Belhassen
la source
0
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
GIJoeCodes
la source