Jak szybko usunąć obramowanie paska nawigacji?


131

Próbowałem usunąć obramowanie NavigationBars bez powodzenia. Zbadałem i ludzie wydają się mówić, aby ustawić shadowImage i BackgroundImage na zero, ale to nie działa w moim przypadku.

Mój kod

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

ilustracja:

wprowadź opis obrazu tutaj

Odpowiedzi:


309

Problem polega na tych dwóch liniach:

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

Ponieważ nie masz obrazu bez nazwy, UIImage(named: "")zwraca nil, co oznacza, że ​​domyślne zachowanie zaczyna działać :

Gdy wartość jest różna, zamiast domyślnego obrazu cienia wyświetlany jest niestandardowy obraz cienia. Aby niestandardowy cień był wyświetlany, niestandardowy obraz tła musi być również ustawiony za pomocą -setBackgroundImage: forBarMetrics: (jeśli używany jest domyślny obraz tła, zostanie użyty domyślny obraz cienia).

Potrzebujesz naprawdę pustego obrazu, więc po prostu zainicjuj UIImage():

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

2
Ta odpowiedź naprawdę działa. Ponieważ jeśli użyjesz zaakceptowanej odpowiedzi (kodu), jego pasek narzędzi usuwania imageViews do.
Sergey Krasiuk

1
To powinna być akceptowana odpowiedź. Działa również podczas ustawiania z UINavigationBar.appearance ()
Heinrisch.

1
To powinna być zaakceptowana odpowiedź dla Swift 3. Zaakceptowana odpowiedź zadziałała dla mnie w Swift 2, ale nie w Swift 3
ColinMasters

1
dla swift3 należy napisać nieco inaczej: self.navigationController? .navigationBar.setBackgroundImage (UIImage (), dla: UIBarMetrics.default) self.navigationController? .navigationBar.shadowImage = UIImage ()
Chetan Dobariya

5
Ta metoda koliduje z dużym tytułem w iOS 11
SteffenK

53

Swift 4 i Swift 5

Usuwanie obramowania:

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

Przywracanie granicy:

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

2
Doskonała odpowiedź :)
PJR

Czy potrzebujemy tutaj layoutIfNeeded ()?
korgx9

1
Tak, korgx9, potrzebujemy tego. W przeciwnym razie nie zmieni koloru do następnego losowania.
Sazzad Hissain Khan

37

spowoduje to całkowite usunięcie obrazu cienia

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

1
Czy mógłbyś to rozwinąć?
Kmeixner

1
U mnie też działa to rozwiązanie, podczas gdy odpowiedź @Nate Cook nie działa. : S
Luca Davanzo

2
Holy sheist !! Po tych wszystkich poszukiwaniach jest to JEDYNA rzecz, która się sprawdziła.
Tuan Anh Vu

to działa, ale mam też ikonę menu na pasku nawigacyjnym i zniknęła: / chcę tylko usunąć obramowanie. POMOC: /
Stephy Samaniego

To zadziałało, ale po wypchnięciu nowego ViewController usuwa stamtąd wiersz do. Jak mogę temu zapobiec?
Anirudha Mahale

36

Dzięki Swift 2 możesz to zrobić w następujący sposób:

Plik AppDelegate

Wewnątrz aplikacji func (..., didFinishLaunchingWithOptions launchOptions: ...)

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

dla Swift 3:

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

Poprawna odpowiedź.
wyd.

To jest wyczerpująca odpowiedź!
madeny

Lepiej jest pisać takie przydatne wartości domyślne w Appdelegate niż zapisywać je w dziwnych miejscach. Dobra odpowiedź :)
Md Rais

35

Po prostu napisz to w rozszerzeniu UINavigationBar

extension UINavigationBar {

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

A w Twoim widoku Kontroler ...

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

Aby cofnąć to działanie dla dowolnego elementu viewController, po prostu przekaż wartość false.


Działa to świetnie, ALE ukrywa się, jeśli dla WSZYSTKICH vcs na stosie nawigacyjnym. Jeśli używasz go w vc1, a vc1 może wypchnąć do vc2, zostanie również ukryty na vc2. Aby pokazać cień w vc2, musisz ustawić go na false w viewDidLoad. Problem polega na tym, że gdy wrócisz do vc1, pojawi się ponownie, ponieważ został zresetowany w vc2. Musisz użyć logiki, aby iść tam iz powrotem, co może nie być tego warte. Jeśli jednak nie chcesz, aby obraz cienia w ogóle był wyświetlany na jakimkolwiek vcs, to jest to najłatwiejszy sposób
Lance Samaria

Powiedzmy, że mamy stos viewControllers z 5 viewControllers (i ukryliśmy cień w pierwszym). Teraz tylko dla trzeciego viewController, ja NIE CHCEMY ukryć cienia. Więc wywołam tę metodę z FALSE w viewWillAppear i TRUE w viewWillDisappear z trzeciego viewController. To wszystko!
Gaurav Chandarana

Twoje absolutnie poprawne, dobre myślenie! Nie myśl, że podniosłem twoją odpowiedź, ponieważ jest bardzo zwięzła i skuteczna, również ją zagłosowałem. Używam go, aby go usunąć i navBar dla komunikatów o błędach. Problem, który znalazłem, dotyczył usuwania go w vc1, ale pokazania go jako vc2, ale jeśli wystąpił błąd w vc2, usunięcie go w viewWillDisappear może nie działać. Ale znowu jest to bardzo wyjątkowa sytuacja. Podoba mi się pomysł viewWillDisappear do ogólnego użytku i powinieneś dodać go do swojej odpowiedzi. Niezależnie od tego, czy Twój kod działa i jest to łatwy sposób na usunięcie cienia! 👍🏿👍🏿
Lance Samaria,

Działa jak marzenie. Chciałeś się tylko upewnić, że to nie są ustawienia prywatne?
inokey

2
To doskonała odpowiedź! Dodałem odpowiedź, która usprawnia kod.
Scott Gardner

13

Ustaw barStylena .Blackprzed ustawieniem odcienia:

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

czy to trochę przypadkowe, że to faktycznie działa? czy za dużo się zastanawiam?
joe

@joe cóż, tutaj działa :-) czy to nie działa dla Ciebie?
gpbl

o to chodzi, to działa. Zastanawiam się tylko, czy istnieje wyjaśnienie, dlaczego zmieniam styl paska na czarny, a następnie zmienia kolor całego paska na niebieski :)
joe

może ustawiając go na czarny i nieprzezroczysty, wyłącza niektóre warstwy / widok na
pasku

Próbowałem tego użyć i usuwa to dolną linię, jednak jeśli
użyję

11

Szybki 5

Podczas używania setBackgroundImage / shadowImage do ukrycia linii włosów występuje niewielkie opóźnienie. Ta metoda usuwa opóźnienie. Podziękowania dla Chameleon Framework . To jest metoda, której używają (w 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, to jedyne rozwiązanie, które działało dla mnie na iOS 13.4 ...
kevinstueber

9

Odpowiedź Luca Davanzo jest świetna, ale nie działa w iOS 10. Zmieniłem ją, żeby działała w iOS 10 i niższych.

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

Możesz także rozszerzyć UINavigationController i wywołać to z tego. removeFromSuperview()na linii nie będzie działać na iOS 10, więc po prostu ustawiłem alfa na 0, więc to jedno połączenie jest kompatybilne wszędzie.


Niezły chwyt, jakikolwiek sposób na pokazanie / ukrycie cienia w niektórych kontrolerach widoku podczas nawigacji?
Ashkan.H

Powinieneś raczej sprawdzić wysokości, które mają height >= 1.0. W modelach iPhone'a z 3-krotnym ekranem siatkówkowym (np. 8 Plus, XR ...) linia włosów ma wysokość 0,33.
fl034

7

Aby usunąć obramowanie z UINavigationBar w Swift 3+, użyj:

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

5

dla szybkiego 3

w viewDidLoadmetodzie

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


4

Zaktualizowano dla Swift 4 na wypadek, gdyby ktoś się zastanawiał

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

Teraz jest jeszcze mniej gadatliwy.


2

Oto sposób, jeśli chcesz to zrobić bez zmiany koloru tła:

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

UWAGA: może to spowodować awarię w aplikacji produkcyjnej. Najwyraźniej pasek nawigacji nie lubi znikać widoku


2

Zaakceptowana odpowiedź zadziałała dla mnie, ale zauważyłem, że gdy chciałem, aby obraz cienia pojawił się ponownie po cofnięciu się lub przesunięciu do przodu do innego vc, zauważalne było mrugnięcie na pasku nawigacyjnym.

Korzystając z tej metody navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") w viewWillAppear pasek cienia jest ukryty w kontrolerze bieżącego widocznego widoku.

Korzystanie z tych 2 metod

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

in viewWillDisappear miganie nadal występuje, ale tylko wtedy, gdy obraz cienia pojawia się ponownie, a nie sam pasek nawigacji.

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

dla swift3 należy napisać nieco inaczej:

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


1

Delegat aplikacji

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

1

Jeśli chcesz usunąć tylko dolną linię i zachować jednolity kolor NavigationBar, dodaj te wiersze kodu w viewDidLoad: Swift 3, 4:

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

Pokój!


0

Linia graniczna to UIImageView, a usunięcie widoku podrzędnego, który jest obrazem, spowoduje usunięcie barButtonItems z UIImageView. Poniższy kod pomoże Ci go usunąć. Mam nadzieję, że pomoże to komuś, kto stanął przed problemem takim jak ja.

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

Obramowanie UIImageView ma tylko 0,5 wysokości, więc ten kod usuwa tylko to.


To spowodowało u mnie awarie. Myślę, że ParentViews i childViews muszą zostać rozpakowane na wypadek, gdyby były zerowe przed sprawdzeniem każdego z nich. Używam jednak niestandardowego UINavigationController, więc może to nie mieć miejsca w przypadku innych użytkowników ze standardowym paskiem.
Natalia,

0

W ramach AppDelegate globalnie zmieniło to format NavBar i usuwa dolną linię / obramowanie:

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

Nie udało mi się zaimplementować niczego innego na konkretnym VC, ale to pomoże 90% ludzi


UINavigationBar.appearance (). BackgroundColor = UIColor.redColor () nie jest wymagana.
sabiland

0

to jest odpowiedź w szybkiej 3 bazie odpowiedzi Nate Cooka

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

0

iOS 11 i Swift 4 Powinieneś spróbować podążać za nimi, jeśli chcesz usunąć obramowanie, ale nie chcesz, aby pasek nawigacyjny był półprzezroczysty
self.navigationBar.shadowImage = UIImage()


0

w swoim niestandardowym kontrolerze nawigacji dodaj następujące wiersze:

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

Ważna uwaga

ostatnia linia jest ważna, jeśli używasz metody viewDidLoad () pierwszej linii, ponieważ navigationController powinien przerysować pasek nawigacyjny, ale łatwo możesz go użyć bez layoutIfNeeded () w metodzie viewWillAppear (), zanim narysuje pasek nawigacji


0

Szybsza metoda Jacka Chena:

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

Za pomocą:

    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()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.