Come rimuovere il bordo della navigationBar in modo rapido?


131

Ho provato a rimuovere il bordo navigationBars senza fortuna. Ho studiato e le persone sembrano dire di impostare shadowImage e BackgroundImage a zero, ma nel mio caso non funziona.

Il mio codice

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

illustrazione:

inserisci qui la descrizione dell'immagine

Risposte:


309

Il problema è con queste due righe:

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

Poiché non hai un'immagine senza nome, UIImage(named: "")restituisce nil, il che significa che il comportamento predefinito entra in gioco:

Quando non è nullo, viene visualizzata un'immagine ombra personalizzata al posto dell'immagine ombra predefinita. Per visualizzare un'ombra personalizzata, è necessario impostare anche un'immagine di sfondo personalizzata con -setBackgroundImage: forBarMetrics: (se viene utilizzata l'immagine di sfondo predefinita, verrà utilizzata l'immagine dell'ombra predefinita).

Hai bisogno di un'immagine veramente vuota, quindi inizializza con UIImage():

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

2
Questa risposta funziona davvero. Perché se usi la risposta accettata (codice), rimuove le imageViews della barra degli strumenti in.
Sergey Krasiuk,

1
Questa dovrebbe essere la risposta accettata. Funziona anche quando si imposta da UINavigationBar.appearance ()
Heinrisch

1
Questa dovrebbe essere la risposta accettata per Swift 3. La risposta accettata ha funzionato per me in Swift 2, ma non in Swift 3
ColinMasters

1
per lo swift3 dovresti scrivere in un modo leggermente diverso: self.navigationController? .navigationBar.setBackgroundImage (UIImage (), per: UIBarMetrics.default) self.navigationController? .navigationBar.shadowImage = UIImage ()
Chetan Dobariya

5
Questo metodo è in conflitto con il titolo grande in iOS 11
SteffenK

53

Swift 4 e Swift 5

Rimozione del bordo:

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

Ripristino del bordo:

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

2
Risposta perfetta :)
PJR

Abbiamo bisogno di layoutIfNeeded () qui?
korgx9

1
Sì korgx9, ne abbiamo bisogno. Altrimenti non cambierà il colore fino alla prossima estrazione.
Sazzad Hissain Khan

37

questo rimuoverà completamente l'immagine dell'ombra

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

1
Potresti elaborare?
Kmeixner

1
Anche per me funziona questa soluzione, mentre la risposta di @Nate Cook non ha funzionato. : S
Luca Davanzo

2
Santo sicario !! Dopo tutta la ricerca, questa è l'UNICA cosa che ha funzionato.
Tuan Anh Vu

funziona, ma ho anche un'icona del menu nella barra di navigazione ed è scomparsa: / Voglio solo che il bordo venga cancellato. AIUTO: /
Stephy Samaniego

Questo ha funzionato per me, ma dopo aver premuto il nuovo ViewController rimuove la linea da lì a. Come posso impedirlo?
Anirudha Mahale

36

Con Swift 2 puoi farlo in questo modo:

File AppDelegate

All'interno dell'applicazione func (..., didFinishLaunchingWithOptions launchOptions: ...)

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

per Swift 3:

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

Risposta corretta.
Ed.

Questa è la risposta esauriente!
madeny

Meglio scrivere valori predefiniti così utili su Appdelegate piuttosto che scriverli nei posti dispari. Risposta giusta :)
Md Rais

35

Basta scrivere questo nell'estensione di UINavigationBar

extension UINavigationBar {

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

E dal tuo punto di vista Controller ...

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

E per annullare l'operazione per qualsiasi viewController, basta passare false.


Funziona alla grande MA si nasconde se per TUTTI i vcs sullo stack di navigazione. Se lo usi in vc1 e vc1 puoi eseguire il push in vc2, sarà nascosto anche su vc2. Per mostrare l'ombra in vc2 dovrai impostarla su false in viewDidLoad. Il problema è che quando torni in vc1 verrà visualizzato di nuovo perché è stato ripristinato in vc2. Devi usare la logica per andare avanti e indietro, il che potrebbe non valerne la pena. Tuttavia, se non vuoi che l'immagine dell'ombra venga mostrata su nessun video, questo è il modo più semplice per andare
Lance Samaria

Supponiamo di avere uno stack di viewControllers con 5 viewControllers (e abbiamo nascosto l'ombra nel primo). Ora solo per il 3 ° viewController, NON vogliamo nascondere l'ombra. Quindi, chiamerò quel metodo con FALSE in viewWillAppear e con TRUE in viewWillDisappear del 3 ° viewController. È tutto ciò che serve!
Gaurav Chandarana

il tuo assolutamente corretto, buon pensiero! Non pensare di aver bussato alla tua risposta perché è molto succinta ed efficiente, l'ho anche votata. Lo uso per rimuoverlo e la navBar per i messaggi di errore. Il problema che ho riscontrato era durante la rimozione in vc1 ma mostrandolo in vc2 ma se si verificava un errore in vc2, rimuoverlo in viewWillDisappear potrebbe non funzionare. Ma ancora una volta è una situazione davvero unica. Mi piace l'idea viewWillDisappear per l'uso generale del caso e dovresti aggiungerla alla tua risposta. Indipendentemente dal fatto che il tuo codice funzioni ed è un modo semplice per rimuovere l'ombra! 👍🏿👍🏿
Lance Samaria

Funziona come un fascino. Volevo solo assicurarti che non si tratti di impostazioni private?
inokey

2
Questa è un'ottima risposta! Ho aggiunto una risposta che semplifica il codice.
Scott Gardner

13

Impostare barStylesu .Blackprima di impostare la tinta:

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

è un po 'casuale che funzioni davvero? o sto pensando troppo?
joe

@joe beh, qui funziona :-) non funziona per te?
gpbl

questo è il punto, funziona. Mi chiedo solo se c'è una spiegazione sul motivo per cui trasformando barStyle in nero, trasforma l'intera barraTintColor in blu :)
joe

magari impostandolo su nero e opaco, spegne alcuni livelli / vista nella
barra di

Ho provato a usarlo e rimuove la linea di fondo, tuttavia se si utilizza una barra di colore bianco il titolo non è visibile: /
RileyDev

11

Swift 5

Quando si usa setBackgroundImage / shadowImage per nascondere l'attaccatura dei capelli, c'è un leggero ritardo. Questo metodo rimuove il ritardo. Ringraziamo Chameleon Framework . Questo è il metodo che usano (in 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, questa è l'unica soluzione che ha funzionato per me su iOS 13.4 ...
kevinstueber

9

La risposta di Luca Davanzo è ottima, ma non funziona su iOS 10. L'ho modificata per funzionare su iOS 10 e versioni precedenti.

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

Puoi anche estendere UINavigationController e richiamarlo. removeFromSuperview()sulla linea non funzionerà su iOS 10, quindi ho impostato l'alfa su 0 in modo che questa chiamata sia compatibile ovunque.


Bella presa, qualche modo per mostrare / nascondere l'ombra in alcuni viewController durante la navigazione?
Ashkan.H

Dovresti piuttosto controllare le altezze con estensione height >= 1.0. Sui modelli di iPhone che hanno uno schermo retina 3x (es. 8 Plus, XR ...) l'attaccatura dei capelli ha un'altezza di 0,33.
fl034

7

Per rimuovere il bordo da UINavigationBar in Swift 3+, usa:

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

5

per swift 3

nel viewDidLoadmetodo

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


4

Aggiornato per Swift 4 nel caso qualcuno se lo stesse chiedendo

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

Ora è ancora meno prolisso.


2

Questo è il modo se vuoi farlo senza cambiare il colore di sfondo:

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

NOTA: questo potrebbe bloccarsi su un'app di produzione. Apparentemente alla NavigationBar non piace che la sua vista scompaia


2

La risposta accettata ha funzionato per me, ma ho notato che quando volevo che l'immagine dell'ombra riapparisse quando tornavo indietro o spingevo in avanti verso un altro vc, c'era un lampo evidente nella barra di navigazione.

Utilizzando questo metodo navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") in viewWillAppear, la barra delle ombre viene nascosta nel controller della vista visibile corrente.

Utilizzando questi 2 metodi

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

in viewWillDisappear continua a lampeggiare ma solo quando ricompare l'immagine ombra e non la barra di navigazione stessa.

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

per swift3 dovresti scrivere in modo leggermente diverso:

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

1

Questa è una versione semplificata della risposta di Gaurav Chandarana .

extension UINavigationBar {

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

1

Delegato dell'app

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

1

Se desideri rimuovere solo la riga inferiore e mantenere il colore solido di navigationBar, aggiungi queste righe di codice in viewDidLoad: Swift 3, 4:

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

Pace!


0

La linea di confine è un UIImageView e la rimozione di una sottoview che è un imageView rimuoverà barButtonItems con UIImageView. Il codice sottostante ti aiuterà a rimuoverlo. Spero che questo aiuti qualcuno che ha affrontato un problema come me.

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

Il bordo UIImageView è alto solo 0,5, quindi questo codice rimuove solo quello.


Ciò ha causato arresti anomali per me. Penso che le viste di genitori e figli debbano essere scartate nel caso siano nulle prima di controllarle ciascuna. Tuttavia, sto utilizzando un UINavigationController personalizzato, quindi questo potrebbe non essere il caso per altri utenti con una barra standard.
Natalia

0

All'interno di AppDelegate , questo ha cambiato globalmente il formato della NavBar e rimuove la linea / bordo inferiore:

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

Non sono riuscito a implementare nulla di diverso su uno specifico VC, ma questo aiuterà il 90% delle persone


UINavigationBar.appearance (). BackgroundColor = UIColor.redColor () non è necessario.
sabiland

0

questa è la risposta in rapida 3 base della risposta di Nate Cook

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

0

iOS 11 e Swift 4 Dovresti provare a seguire se vuoi rimuovere il bordo ma non rendere traslucida la barra di navigazione
self.navigationBar.shadowImage = UIImage()


0

nella tua navigazione personalizzataController aggiungi queste righe:

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

Nota importante

l'ultima riga è importante se usi la prima riga metodo viewDidLoad () perché navigationController dovrebbe ridisegnare la barra di navigazione ma puoi usarla facilmente senza layoutIfNeeded () nel metodo viewWillAppear () prima che disegni la barra di navigazione


0

Metodo più rapido di 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
    }
}

usando:

    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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.