Sombra escura na barra de navegação durante a transição segue após a atualização para Xcode 5.1 e iOS 7.1

91

Quando estou navegando para frente e para trás entre os controladores pai e filho em um controlador de navegação mestre-detalhe, vejo uma sombra escura no lado direito da barra de navegação na parte superior. Tudo começou depois que atualizei para o Xcode 5.1. É uma sensação áspera e perturbadora. Como posso me livrar disso?

Nihat
fonte

Respostas:

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

Resolvi esse problema definindo a cor de fundo da visualização do controlador de navegação.

não-amanteigado
fonte
Esta resposta é realmente muito boa. Por alguma razão, o Interface Builder não permite que você acesse a visualização do seu controlador de navegação, mas parece que uma darkColorvisualização ainda está lá e causa este problema.
superarts.org
1
Esta é uma ótima resposta porque também permite que a barra permaneça translúcida enquanto não mostra a seção preta feia que vaza do controlador de navegação. Só queria que houvesse uma maneira de configurá-lo no storyboard.
dimiguel
Exatamente. De vez em quando penso nisso e fico um pouco decepcionado com as outras respostas que sugerem desligar a transparência da barra de navegação, pois basicamente estão resolvendo esse problema desabilitando um recurso, que esta resposta aponta a correção real. Pena que esse comportamento continua o mesmo no Xcode 7 / iOS 9.
superarts.org
1
Desculpe, eu votei contra esta resposta porque o plano de fundo da janela não é a causa raiz para este problema. Por favor, veja minha captura de tela em anexo: imgur.com/a/SH5Dp Você vai descobrir que o problema ainda existe, a sombra escura acabou de ser substituída por uma branca, acho que o controlador de detalhes foi 'cortado' ou de alguma forma, faça com que não desenhe nada sob NavBar .
mariotaku
1
tabBarController? .view.backgroundColor = UIColor.white caso se o controlador raiz seja UITabBarController.
Vishal Singh
53
self.navigationController.navigationBar.translucent = NO; 

consertou

Nihat
fonte
Onde você colocou isso?
Zorayr
No método ViewDidLoad do controlador de visualização mestre
Nihat
adicionar visualizaçãoDidAppear
Abdul Waheed
Acho que essa é realmente a resposta correta. o navigationController.view.backgroundColor = .whitenão funciona mais no iOS 11.
AnBisw
1
@Annjawn, navigationController.view.backgroundColor = .whitefunciona no iOS 12. Remover translúcido da barra de navegação não pode ser usado em situações quando é necessário, mas a sombra preta não é.
Alex Motor
38

a resposta de nonamelive é perfeita. Para obter a mesma coisa no Interface Builder E AINDA MANTER A TRANSLUCÊNCIA , selecione o controlador de navegação e defina um atributo de tempo de execução definido pelo usuário view.backgroundColorcomo mostrado na captura de tela (no Inspetor de Identidade). Repita para todos os controladores de navegação que apresentam este problema.

Parece que todo esse problema ocorre porque a cor preta (ou, na verdade, nenhuma cor) de UINavigationController está vazando no momento em que o CoreGraphics faz um instantâneo dele no início da animação. Portanto, defini-lo como branco impedirá isso.

Inspetor de identidade -> Atributos de tempo de execução definidos pelo usuário

manmal
fonte
1
Eu prefiro essa abordagem, deixe a interface do Builder lidar com o máximo possível.
DazChong
iOS 8.4 não ajudou
Maksim Kniazev
3
Funciona perfeitamente com o Xcode 8.3.3. Apenas para enfatizar novamente, deve ser UINavigationControllerativado, não no viewController.
jungledev
Eu tinha um navcon em um tabcon e vi sombras nas duas barras (superior e inferior) ao usar "Oculta a barra inferior ao empurrar" em um dos VCs do navcon. Definir o fundo branco no navcon corrigiu ambas as sombras. Obrigado!
nh32rg
6

Este parece ser um bug que foi introduzido no iOS 7.1. No meu caso, é causado por uma UIToolbar colocada diretamente abaixo da barra de navegação. A sombra escura também aparece na barra de guias translúcida.

A sombra parece ser causada pela visualização do plano de fundo do UIToolbar. Agora, uso esta solução alternativa no controlador de visualização com a barra de ferramentas que oculta a visualização do plano de fundo da barra de ferramentas durante a transição:

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

Este é o código para [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

Eu preenchi este Radar: http://openradar.appspot.com/16418845

tom
fonte
2
Sua solução é boa se você não quiser uma barra de navegação translúcida.
tomo
Existe uma maneira mais fácil de obter o backgroundView. [self.toolbar valueForKey:@"_backgroundView"]. Observe que esta é uma API privada, mas acho que você não será pego pela Apple porque _backgroundViewé apenas um nome genérico.
nonamelive
Essa resposta me deu uma dica do que eu precisava fazer. No meu caso, foi tão simples quanto desmarcar a opção translúcido no UIToolbar no construtor de interface.
Greg W
4

Parece acontecer com qualquer barra (TabBar ou ToolBar) que é translúcida.
Portanto, uma maneira de corrigir isso é definir o _tabBar.translucent = NO;(no meu caso). Isso evita a sombra indesejada sob a barra de navegação superior, deixando a barra de navegação translúcida. Infelizmente, a barra inferior não é mais translúcida.

Pode ser definido de volta para translúcido, mas tudo isso tem que acontecer depois que toda a animação de empurrar for concluída, portanto, a alteração dessa propriedade é bem perceptível.

No caso, no entanto, a barra inferior também deve ser translúcida e não quero que o usuário veja a alteração, resolvi com o seguinte:

/*  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];
                 }];

Então, no viewDidAppear:eu simplesmente reverto isso:

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

Há apenas uma pequena mudança na aparência, especialmente, mas é quase imperceptível e é muito melhor do que ter a sombra sob a barra de navegação.

Espero que ajude outras pessoas a manter as barras translúcidas até que a Apple conserte esse comportamento, já que as barras SÃO destinadas a ficar ocultas em alguns casos, ao contrário do que foi sugerido em outros posts especialmente para o UITabBar

kacho
fonte
Consegui corrigir esse problema adotando a solução de @manmal - definir o atributo runtime view.backgroundColorpara seu UITabBarController no storyboard e configurá-lo para uma cor branca.
Jamesk
4

Isso funciona para mim no Swift

Em AppDelegateno didFinishLaunchingWithOptionsmétodo, eu definir esta:

UIApplication.shared.windows.first?.backgroundColor = .white
pableiros
fonte
4

Isso funciona para mim no iOS 13 com temas claros e escuros e também em versões mais antigas do iOS.

Adicione o seguinte código ao AppDelegate ao application(didFinishLaunchingWithOptions)método:

if #available(iOS 13.0, *) {
    window?.backgroundColor = UIColor.systemBackground
} else {
    window?.backgroundColor = UIColor.white
}
Petrsyn
fonte
Eu também tentei esse método, mas enfrento um problema ao apresentar um controlador de visualização no modo padrão. Então você verá o fundo branco da janela em vez do preto. Isso parece estranho. você pode sugerir alguma ideia para superar esta situação
varun v nair
3

Aqui está minha variação ... requer muito menos código do que a resposta do tom e é mais eficiente. Isso é SE você quiser uma barra de navegação translúcida e também corrigir o problema de sombra.

No ViewController de origem (que está embutido no Controlador de navegação) ...

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

e

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

O resultado é o mesmo que Tom faz (visualmente, para o usuário final) e é mais fácil de implementar. Espero que isto ajude...

user2734823
fonte
3
self.navigationController!.navigationBar.translucent = false;

Isso funciona para mim, colocando-o dentro da função onde você empurra o novo ViewController

Shyam Raju
fonte
Loucura, mas entre todas as respostas, a ideia de colocá-lo na função empurrando para o próximo VC foi essa!
Coltuxumab
3

O seguinte também funciona e deixa a barra de navegação transparente:

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

seb
fonte
1

Embora não seja igual à implementação padrão do iOS, esta é uma boa maneira de corrigir o problema:

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

Você obterá uma bela animação fade-in / fade-out da barra de guias. Adicione o código na raiz UIViewController.

Nikolovski
fonte
-1

Ou se você estiver usando o construtor de interface, você pode apenas selecionar Barra de Navegação em seu controlador de navegação e desmarcar a caixa de seleção Translúcida entre Estilo e Matiz de Barra no Inspetor de Atributos para se livrar daquele efeito estranho -

Inspetor

novato
fonte