Como remover borda da barra de navegação em swift?

131

Eu tenho tentado remover a borda navigationBars sem sorte. Eu pesquisei e as pessoas parecem dizer para definir shadowImage e BackgroundImage para zero, mas isso não funciona no meu caso.

Meu código

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

ilustração:

insira a descrição da imagem aqui

Peter Pik
fonte

Respostas:

309

O problema é com estas duas linhas:

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

Como você não tem uma imagem sem nome, UIImage(named: "")retorna nil, o que significa que o comportamento padrão entra em ação:

Quando não nulo, uma imagem de sombra personalizada a ser exibida em vez da imagem de sombra padrão. Para que uma sombra personalizada seja mostrada, uma imagem de plano de fundo personalizada também deve ser configurada com -setBackgroundImage: forBarMetrics: (se a imagem de plano de fundo padrão for usada, a imagem de sombra padrão será usada).

Você precisa de uma imagem realmente vazia; basta inicializar com UIImage():

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
Nate Cook
fonte
2
Esta resposta realmente funciona. Porque, se usar resposta aceita (código), sua barra de ferramentas remover imageViews to.
Sergey Krasiuk
1
Essa deve ser a resposta aceita. Também funciona quando a criação de UINavigationBar.appearance ()
Heinrisch
1
Esta deve ser a resposta aceito para Swift 3. A resposta aceita trabalhou para mim em Swift 2, mas não em Swift 3
ColinMasters
1
para o swift3 você deve escrever maneira ligeiramente diferente: self.navigationController .navigationBar.setBackgroundImage (UIImage (), para: UIBarMetrics.default)? self.navigationController .navigationBar.shadowImage = UIImage ()
Chetan Dobariya
5
Este método está em conflito com o título grande no iOS 11
SteffenK 17/17/17
54

Swift 4 e Swift 5

Removendo borda:

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

Restaurando borda:

self.navigationController?.navigationBar.setBackgroundImage(nil, for:.default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.layoutIfNeeded()
Sazzad Hissain Khan
fonte
2
Resposta perfeita :)
PJR
Precisamos de layoutIfNeeded () aqui?
Korgx9
1
Sim korgx9, precisamos disso. Caso contrário, não mudará a cor até o próximo sorteio.
Sazzad Hissain Khan
37

isso removerá completamente a imagem da sombra

for parent in self.navigationController!.navigationBar.subviews {
 for childView in parent.subviews {
     if(childView is UIImageView) {
         childView.removeFromSuperview()
     }
 }
}
Steve Payne
fonte
1
Você poderia elaborar?
Kreixner # 04/15
1
Também para mim funciona esta solução, enquanto a resposta de @Nate Cook não funcionou. : S
Luca Davanzo 19/10/2015
2
Santo sheist !! Depois de toda a pesquisa, essa é a ÚNICA coisa que funcionou.
Tuan Anh Vu
funciona, mas também tenho um ícone de menu na barra de navegação e desapareceu: / eu só quero que a borda seja apagada. Ajuda: /
Stephy Samaniego
Isso funcionou para mim, mas depois de pressionar o novo ViewController, ele remove a linha de lá para. Como posso evitar isso?
Anirudha Mahale #
36

Com o Swift 2, você pode fazer o seguinte:

Arquivo AppDelegate

Aplicativo func interno (..., didFinishLaunchingWithOptions launchOptions: ...)

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

para Swift 3:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
Jorge Casariego
fonte
Resposta correta.
Ed.
Esta é a resposta abrangente!
madeny
Melhor escrever esses padrões úteis no Appdelegate do que escrevê-los em lugares estranhos. Resposta Correta :) #
21419 Md Rais
35

Basta escrever isso na extensão do UINavigationBar

extension UINavigationBar {

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

E, na sua opinião, Controlador ...

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

E para desfazer isso para qualquer viewController, basta passar false.

Gaurav Chandarana
fonte
Isso funciona muito bem, mas oculta para TODOS os vcs na pilha de navegação. Se você usá-lo em vc1 e vc1 pode enviar para vc2, ele também ficará oculto em vc2. Para mostrar a sombra em vc2, você precisará defini-la como false em viewDidLoad. O problema é que quando você voltar ao vc1, ele será exibido novamente porque foi redefinido no vc2. Você precisa usar a lógica para ir e voltar, o que pode não valer a pena. No entanto, se você não quer que a imagem sombra para exibição em qualquer vcs em tudo, então esta é a maneira mais fácil de ir
Lance Samaria
Digamos que temos uma pilha de viewControllers com 5 viewControllers (e escondemos a sombra no primeiro). Agora, apenas para o terceiro viewController, NÃO queremos ocultar a sombra. Então, chamarei esse método com FALSE no viewWillAppear e TRUE no viewWillDisappear do 3rd viewController. Isso é tudo o que é necessário!
Gaurav Chandarana,
seu absolutamente correto, bom pensamento! Não pense que bati na sua resposta, porque é muito sucinta e eficiente, eu também votei nela. Eu o uso para removê-lo e a navBar para obter mensagens de erro. O problema que encontrei foi ao removê-lo em vc1, mas mostrando-o em vc2, mas se houve um erro em vc2, removê-lo em viewWillDisappear pode não funcionar. Mas, novamente, é uma situação muito única. Eu gosto da idéia viewWillDisappear para uso geral de casos e você deve adicioná-la à sua resposta. Independentemente do seu código funcionar, é uma maneira fácil de remover a sombra! 👍🏿👍🏿
Lance Samaria
Funciona como um encanto. Só queria ter certeza de que não são configurações particulares?
Inokey # 19/17
2
Esta é uma excelente resposta! Eu adicionei uma resposta que simplifica o código.
21418 Scott Gardner
13

Defina barStylecomo .Blackantes de definir a tonalidade:

self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()
gpbl
fonte
é meio aleatório que isso realmente funcione? ou estou pensando demais?
joe
@ joe bem, ele está trabalhando aqui :-) não funciona para você?
Gpbl 30/07/2015
é isso mesmo, funciona. eu estou apenas querendo saber se há uma explicação de por que virar a barStyle para preto-lo, em seguida, transforma toda a barTintColor para :) azul
joe
talvez defini-lo como preto e opaco, desliga-se algumas camadas / vista no NavigationBar ...
gpbl
Eu tentei usar isso, e ele remove a linha inferior no entanto, se usando uma tonalidade de barra de branco, o título não é visível: /
RileyDev 6/15
11

Swift 5

Ao usar setBackgroundImage / shadowImage para ocultar a linha do cabelo, há um pequeno atraso. Este método remove o atraso. Crédito para Chameleon Framework . Este é o método que eles usam (no 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
fonte
1
FWIW, esta é a única solução que funcionou para mim no iOS 13.4 ...
kevinstueber 10/04
9

A resposta de Luca Davanzo é ótima, mas não funciona no iOS 10. Eu a alterei para funcionar no iOS 10 e abaixo.

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

Você também pode estender o UINavigationController e cancelar isso. removeFromSuperview()na linha não funcionará no iOS 10, então apenas defino o alfa como 0 para que esta chamada seja compatível em qualquer lugar.

David Baez
fonte
Boa captura, alguma maneira de mostrar / ocultar a sombra em alguns viewControllers durante a navegação?
precisa saber é o seguinte
Você deve verificar as alturas que possuem um height >= 1.0. Nos modelos de iPhone que possuem uma tela retina 3x (por exemplo, 8 Plus, XR ...), a linha do cabelo tem uma altura de 0,33.
fl034 13/03/19
7

Para remover a borda do UINavigationBar no Swift 3+, use:

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

para swift 3

no viewDidLoadmétodo

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

Só isso funcionou para mim,

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

Ref.

Mohammad Zaid Pathan
fonte
4

Atualizado para o Swift 4 caso alguém esteja se perguntando

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

É ainda menos detalhado agora.

Mauricio Chirino
fonte
2

É assim que você deseja fazer sem alterar a cor do plano de fundo:

// 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: Isso pode falhar em um aplicativo de produção. Aparentemente, o NavigationBar não gosta que sua visualização desapareça

Yariv Nissim
fonte
2

A resposta aceita funcionou para mim, mas notei quando queria que a imagem da sombra reaparecesse ao voltar ou avançar para outro vc, houve um piscar visível na barra de navegação.

Usando esse método navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") no viewWillAppear, a barra de sombra está oculta no atual controlador de exibição visível.

Usando esses 2 métodos

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

em viewWillDisappear o piscar ainda acontece, mas somente quando a imagem de sombra reaparece e não a barra de navegação.

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
fonte
1

para o swift3, você deve escrever de maneira ligeiramente diferente:

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

Esta é uma versão simplificada da resposta de Gaurav Chandarana .

extension UINavigationBar {

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

Delegado do aplicativo

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
CSE 1994
fonte
1

Se você deseja remover apenas a linha inferior e manter a cor sólida da barra de navegação, adicione essas linhas de código em viewDidLoad: Swift 3, 4:

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

Paz!

Mihail Salari
fonte
0

A linha de borda é uma UIImageView e a remoção de uma subvisão que é uma imageView removerá barButtonItems com UIImageView. O código abaixo o ajudará a removê-lo. Espero que isso ajude alguém que enfrentou um problema como eu.

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

A borda UIImageView tem apenas 0,5 de altura; portanto, esse código remove apenas isso.

bachman
fonte
Isso causou falhas para mim. Acho que pais e filhos precisam ser desembrulhados caso sejam nulos antes de verificar cada um. No entanto, estou usando um UINavigationController personalizado, portanto, pode não ser o caso para outros usuários com uma barra padrão.
Natalia
0

No AppDelegate , isso mudou globalmente o formato da NavBar e remove a linha inferior / borda:

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

Não conseguiu implementar nada diferente em um VC específico, mas isso ajudará 90% das pessoas

David West
fonte
UINavigationBar.appearance (). BackgroundColor = UIColor.redColor () não é necessário.
sabiland 24/05
0

esta é a resposta na rápida base 3 da resposta Nate Cook

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

iOS 11 e Swift 4 Você deve tentar seguir se deseja remover a borda, mas não tornar a barra de navegação translúcida
self.navigationBar.shadowImage = UIImage()

BilalReffas
fonte
0

em seu navigationController personalizado, adicione estas linhas:

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

Nota importante

a última linha é importante se você usar o método viewDidLoad () da primeira linha porque o navigationController deve redesenhar a barra de navegação, mas você pode usá-lo facilmente sem layoutIfNeeded () no método viewWillAppear () antes de desenhar a barra de navegação

Mr Zee
fonte
0

Método mais rápido 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
    }
}

Usando:

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

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isHiddenHairline = false
    }
Mickael Belhassen
fonte
0
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
GIJoeCodes
fonte