Ciemny cień na pasku nawigacyjnym podczas przejścia płynnego po aktualizacji do Xcode 5.1 i iOS 7.1

91

Kiedy nawiguję tam i z powrotem między kontrolerami nadrzędnymi i podrzędnymi w kontrolerze nawigacyjnym nadrzędnym - szczegóły, widzę ciemny cień po prawej stronie paska nawigacyjnego u góry. Zaczęło się po uaktualnieniu do Xcode 5.1. Jest szorstki i rozpraszający. Jak mogę się go pozbyć?

Nihat
źródło

Odpowiedzi:

144
self.navigationController.view.backgroundColor = [UIColor whiteColor];

Rozwiązałem ten problem ustawiając kolor tła widoku kontrolera nawigacji.

nonamelive
źródło
Ta odpowiedź jest właściwie bardzo dobra. Z jakiegoś powodu Interface Builder nie pozwala na dostęp do widoku kontrolera nawigacyjnego, ale wygląda na to, że darkColorwidok wciąż tam jest i powoduje ten problem.
superarts.org
1
To świetna odpowiedź, ponieważ pozwala również, aby pasek pozostał półprzezroczysty, nie pokazując brzydkiej czarnej sekcji, która przecieka z kontrolera nawigacyjnego. Szkoda tylko, że nie ma sposobu, aby ustawić to w scenorysie.
dimiguel
Dokładnie. Od czasu do czasu o tym myślę i trochę się rozczarowuję innymi odpowiedziami, które sugerują wyłączenie przezroczystości paska nawigacji, ponieważ w zasadzie rozwiązują ten problem poprzez wyłączenie funkcji, na którą ta odpowiedź wskazuje rzeczywistą poprawkę. Szkoda, że ​​to zachowanie pozostaje takie samo w Xcode 7 / iOS 9.
superarts.org
1
Przepraszam, odrzuciłem tę odpowiedź, ponieważ tło okna nie jest główną przyczyną tego problemu. Proszę zobaczyć mój zrzut ekranu w załączeniu: imgur.com/a/SH5Dp Przekonasz się , że problem nadal istnieje, ciemny odcień właśnie zastąpiony białym, wydaje mi się, że kontroler szczegółów został `` przycięty '' lub w jakiś sposób nie rysuje niczego pod NavBar .
mariotaku
1
tabBarController? .view.backgroundColor = UIColor.white w przypadku, gdy kontrolerem głównym jest UITabBarController.
Vishal Singh,
55
self.navigationController.navigationBar.translucent = NO; 

Nowsze wersje Swift:

navigationController?.navigationBar.isTranslucent = false
Nihat
źródło
Gdzie to umieściłeś?
Zorayr
W metodzie ViewDidLoad głównego kontrolera widoku
Nihat
dodaj w widokuDidAppear
Abdul Waheed
myślę, że to jest rzeczywiście prawidłowa odpowiedź. navigationController.view.backgroundColor = .whitejuż nie działa na iOS 11.
AnBisw
1
@Annjawn, navigationController.view.backgroundColor = .whitedziała na iOS 12. Usunięcie półprzezroczystego z paska nawigacji nie może być używane w sytuacji, gdy jest to potrzebne, ale czarny cień nie.
Alex Motor
38

odpowiedź nonamelive jest doskonała. Aby osiągnąć to samo w programie Interface Builder I WCIĄŻ ZACHOWAĆ TRANSLUCENCY , wybierz kontroler nawigacji i ustaw zdefiniowany przez użytkownika atrybut środowiska wykonawczego, view.backgroundColorjak pokazano na zrzucie ekranu (w Inspektorze tożsamości). Powtórz te czynności dla wszystkich kontrolerów nawigacji, które mają ten problem.

Wygląda na to, że cały ten problem występuje, ponieważ czarny kolor (a właściwie brak koloru) UINavigationController przecieka w momencie, gdy CoreGraphics wykonuje migawkę na początku animacji. Więc ustawienie go na biały zapobiegnie temu.

Inspektor tożsamości -> Atrybuty środowiska uruchomieniowego zdefiniowane przez użytkownika

manmal
źródło
1
Wolę takie podejście, pozwól, aby interfejs Interface Builder był jak największy.
DazChong,
iOS 8.4 nie pomógł
Maksim Kniazev
3
Doskonale współpracuje z Xcode 8.3.3. Aby jeszcze raz podkreślić, musi być włączona UINavigationController, a nie na kontrolerze viewController.
jungledev
Miałem navcona w tabconie i widziałem cienie na obu paskach (u góry iu dołu), gdy używałem "Ukrywa dolny pasek przy wypychaniu" na jednym z VC navcona. Ustawienie białego tła na navconie naprawiło oba cienie. Dzięki!
nh32rg
6

Wygląda na to, że jest to błąd wprowadzony w iOS 7.1. W moim przypadku jest to spowodowane przez pasek narzędzi UIT umieszczony bezpośrednio pod paskiem nawigacji. Ciemny cień pojawia się również na półprzezroczystym pasku kart.

Cień wydaje się być spowodowany widokiem tła paska narzędzi UIToolbar. Teraz używam tego obejścia w kontrolerze widoku z paskiem narzędzi, który ukrywa widok tła paska narzędzi podczas przejścia:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    UIView *toolbarBackgroundView = [self.toolbar findViewRecursively:^BOOL(UIView *subview, BOOL *stop) {
        BOOL isToolbarBackgroundView = ([subview isKindOfClass:[UIImageView class]]
                                        && [NSStringFromClass(subview.class) isEqualToString:@"_UIToolbarBackground"]);
        if (isToolbarBackgroundView) {
            *stop = YES;
        }
        return (! isToolbarBackgroundView);
    }];
    if (toolbarBackgroundView) {
        // fade toolbar background view back in
        [UIView animateWithDuration:0.1f animations:^{
            toolbarBackgroundView.alpha = 1.0f;
        }];
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    UIView *toolbarBackgroundView = [self.toolbar findViewRecursively:^BOOL(UIView *subview, BOOL *stop) {
        BOOL isToolbarBackgroundView = ([subview isKindOfClass:[UIImageView class]]
                                        && [NSStringFromClass(subview.class) isEqualToString:@"_UIToolbarBackground"]);
        if (isToolbarBackgroundView) {
            *stop = YES;
        }
        return (! isToolbarBackgroundView);
    }];
    if (toolbarBackgroundView) {
        // hide toolbar background view
        toolbarBackgroundView.alpha = 0.0f;
    }
}

To jest kod dla [UIView findViewRecursively:]

@interface UIView (FindSubview)

- (UIView*)findViewRecursively:(BOOL(^)(UIView* subview, BOOL* stop))recurse;

@end

@implementation UIView (FindSubview)

- (UIView*)findViewRecursively:(BOOL(^)(UIView* subview, BOOL* stop))recurse {
    for (UIView* subview in self.subviews) {
        BOOL stop = NO;
        if (recurse(subview, &stop)) {
            UIView* view = [subview findViewRecursively:recurse];
            if (view) return view;
        } else if (stop) {
            return subview;
        }
    }
    return nil;
}

@end

Złożyłem ten Radar: http://openradar.appspot.com/16418845

Tomek
źródło
2
Twoje rozwiązanie jest w porządku, jeśli nie chcesz przezroczystego paska nawigacji.
tom
Jest łatwiejszy sposób na uzyskanie pliku backgroundView. [self.toolbar valueForKey:@"_backgroundView"]. Pamiętaj, że jest to prywatny interfejs API, ale myślę, że Apple nie złapie Cię, ponieważ _backgroundViewjest to tylko nazwa ogólna.
nonamelive
Ta odpowiedź dała mi wskazówkę, co muszę zrobić. W moim przypadku było to tak proste, jak odznaczenie opcji półprzezroczystej na pasku narzędzi UIT w kreatorze interfejsów.
Greg W.
4

Wydaje się, że dzieje się tak z każdym paskiem (TabBar lub ToolBar), który jest półprzezroczysty.
Tak więc jednym ze sposobów rozwiązania tego problemu jest ustawienie _tabBar.translucent = NO;(w moim przypadku). Zapobiega to niepożądanemu cieniu pod górnym paskiem nawigacji, pozostawiając półprzezroczysty pasek nawigacji. Niestety dolny pasek nie jest już przezroczysty.

Można ją ustawić z powrotem na półprzezroczystą, ale wszystko to musi nastąpić po zakończeniu całej animacji wypychania, więc przełączanie tej właściwości jest dobrze zauważalne.

W przypadku jednak, gdy dolny pasek również musi być półprzezroczysty i nie chcę, aby użytkownik widział zmianę, rozwiązałem to w następujący sposób:

/*  create a simple quick animation of the bottom bar
    just before pushing the new controller */
[UIView animateWithDuration:0.1
                 animations:^{
                     _tabBar.barTintColor = [UIColor colorWithWhite:0.97254901960784 alpha:1.0]; // this is the closest color for my case
                     _tabBar.translucent = NO;
                 } completion:^(BOOL finished) {
                     /* now when the animation that makes the bar not translucent
                        is finished we can push the new controller
                        the controller is instantiated before the animation code */
                     [self.navigationController pushViewController:controller animated:YES];
                 }];

Następnie w viewDidAppear:I po prostu cofam to z powrotem:

[UIView animateWithDuration:0.1
             animations:^{
                     _tabBar.barTintColor = nil;
                     _tabBar.translucent = YES;
                 }];

Występuje tylko niewielka zmiana w wyglądzie, ale jest ledwo zauważalna i jest o wiele lepsza niż posiadanie cienia pod paskiem nawigacji.

Mam nadzieję, że pomoże to innym zachować półprzezroczyste paski, dopóki Apple nie naprawi tego zachowania, ponieważ paski SĄ przeznaczone do ukrywania w niektórych przypadkach, w przeciwieństwie do sugerowanych w innych postach, szczególnie dla UITabBar

kacho
źródło
Udało mi się rozwiązać ten problem, przyjmując rozwiązanie @ manmal - zdefiniuj atrybut środowiska wykonawczego view.backgroundColordla swojego UITabBarController w scenorysie i ustaw go na biały kolor.
jamesk
4

To działa dla mnie w Swift

W AppDelegatesprawie didFinishLaunchingWithOptionssposobu, ustawić w ten sposób:

UIApplication.shared.windows.first?.backgroundColor = .white
pableiros
źródło
4

Działa to dla mnie na iOS 13 z jasnymi i ciemnymi motywami, a także na starszych wersjach iOS.

Dodaj następujący kod do AppDelegate do application(didFinishLaunchingWithOptions)metody:

if #available(iOS 13.0, *) {
    window?.backgroundColor = UIColor.systemBackground
} else {
    window?.backgroundColor = UIColor.white
}
petrsyn
źródło
Ja też wypróbowałem tę metodę, ale napotykam problem podczas prezentowania kontrolera widoku w trybie domyślnym. Wtedy zobaczysz białe tło okna zamiast czarnego. To wygląda dziwnie. czy możesz zasugerować jakiś pomysł na przezwyciężenie tej sytuacji
varun v nair
3

Oto moja odmiana ... wymaga znacznie mniej kodu niż odpowiedź Toma i jest bardziej wydajna. To jest JEŚLI chcesz mieć przezroczysty pasek nawigacyjny, a także chcesz rozwiązać ten problem z cieniem.

W źródle ViewController (osadzonym w kontrolerze nawigacji) ...

- (void)viewDidAppear:(BOOL)animated
{
     self.navigationController.navigationBar.translucent = YES;
}

i

 - (void)viewWillDisappear:(BOOL)animated
 {
     self.navigationController.navigationBar.translucent = NO;
 }

Rezultat jest taki sam, jak to, co robi Tom (wizualnie, dla użytkownika końcowego) i jest łatwiejszy do wdrożenia. Mam nadzieję że to pomoże...

user2734823
źródło
3
self.navigationController!.navigationBar.translucent = false;

To działa dla mnie, umieść go w funkcji, w której naciskasz nowy ViewController

Shyam Raju
źródło
Szalony, ale spośród wszystkich odpowiedzi pomysł umieszczenia go w funkcji pchającej do następnego VC był jednym!
Coltuxumab
3

Poniższe również działa i pozostawia pasek nawigacji przezroczysty:

[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor whiteColor];

seb
źródło
1

Chociaż nie jest to to samo, co standardowa implementacja systemu iOS, jest to dobry sposób na rozwiązanie problemu:

- (void)viewWillAppear:(BOOL)animated {
    [UIView animateWithDuration:0.35f animations:^{
        self.tabBarController.tabBar.alpha = 1.0f;
    }];
}

- (void)viewWillDisappear:(BOOL)animated {
    [UIView animateWithDuration:0.35f animations:^{
        self.tabBarController.tabBar.alpha = 0.0f;
    }];
}

Otrzymasz ładną animację pojawiania się / zanikania paska kart. Dodaj kod w katalogu głównym UIViewController.

Nikolovski
źródło
-1

Lub jeśli korzystasz z narzędzia do tworzenia interfejsu, możesz po prostu wybrać pasek nawigacji z kontrolera nawigacyjnego i odznaczyć pole wyboru Półprzezroczysty między stylem a odcieniem paska w inspektorze atrybutów, aby pozbyć się tego dziwnego efektu -

Inspektor

Nowicjusz
źródło