Objective c 升级到Xcode 5.1和iOS 7.1后,在segue过渡期间导航栏上出现暗影

Objective c 升级到Xcode 5.1和iOS 7.1后,在segue过渡期间导航栏上出现暗影,objective-c,uinavigationcontroller,uinavigationbar,segue,Objective C,Uinavigationcontroller,Uinavigationbar,Segue,当我在主-细节导航控制器中的父控制器和子控制器之间来回导航时,我看到顶部导航栏右侧有一个黑影。它是在我升级到Xcode 5.1之后开始的。这感觉很粗糙,让人分心。我怎样才能摆脱它 self.navigationController.navigationBar.translucent = NO; 对于较新的Swift版本: navigationController?.navigationBar.isTranslucent = false 这似乎是iOS 7.1中引入的一个bug。在我的例子中

当我在主-细节导航控制器中的父控制器和子控制器之间来回导航时,我看到顶部导航栏右侧有一个黑影。它是在我升级到Xcode 5.1之后开始的。这感觉很粗糙,让人分心。我怎样才能摆脱它

self.navigationController.navigationBar.translucent = NO; 
对于较新的Swift版本:

navigationController?.navigationBar.isTranslucent = false

这似乎是iOS 7.1中引入的一个bug。在我的例子中,它是由位于导航栏正下方的UIToolbar引起的。黑色阴影也会出现在半透明选项卡栏中

阴影似乎是由UIToolbar的背景视图造成的。现在,我在视图控制器中使用此变通方法,使工具栏在转换期间隐藏工具栏的背景视图:

- (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;
    }
}
这是
[UIView findviewer:

@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

我归档了这个雷达:

这是我的变体……它需要的代码比tom的答案少得多,而且效率更高。这是如果您想要一个半透明的导航栏,并且还想要修复阴影问题

在源ViewController(嵌入导航控制器中)中


结果与Tom所做的相同(对最终用户而言是可视化的),并且更易于实现。希望这能有所帮助……

虽然它与股票iOS实现不同,但这是解决问题的好方法:

- (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;
    }];
}
您将在选项卡栏中获得一个漂亮的淡入/淡出动画。在根
UIViewController
中添加代码

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

我通过设置导航控制器视图的背景色解决了这个问题。

任何半透明的栏(选项卡栏或工具栏)都会出现这种情况。
因此,解决此问题的一种方法是设置
\u tabBar.translucent=NO(在我的例子中)。这可以防止顶部导航栏下方出现不需要的阴影,同时使导航栏保持半透明。不幸的是,底部栏不再是半透明的

它可以设置回半透明,但所有这些都必须在整个推送动画完成后发生,因此切换此属性非常明显

但是,在这种情况下,底部栏也必须是半透明的,我不希望用户看到我用以下方法解决的更改:

/*  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];
                 }];
然后在
视图中显示:
我只需将其还原为:

[UIView animateWithDuration:0.1
             animations:^{
                     _tabBar.barTintColor = nil;
                     _tabBar.translucent = YES;
                 }];
在外观上有一些特别的变化,但几乎不明显,这比在导航栏下有阴影要好得多


希望它能帮助其他人保持条形图的半透明性,直到苹果修复这种行为,因为条形图在某些情况下是隐藏的,不像其他帖子中建议的那样,特别是对于
uitabar

或者如果您使用的是interface builder,您只需从导航控制器中选择导航栏,并在属性检查器中取消选中“样式”和“栏色调”之间的“半透明”复选框,即可消除这种奇怪的效果-


诺梅利夫的答案是完美的。要在Interface Builder中实现同样的效果,并且仍然保持半透明,请选择导航控制器并设置用户定义的运行时属性
view.backgroundColor
,如屏幕截图(在Identity Inspector中)所示。对显示此问题的所有导航控制器重复此操作

整个问题的出现似乎是因为在动画开始时CoreGraphics对UINavigationController进行快照时,UINavigationController的黑色(或者实际上没有颜色)正在泄漏。因此,将其设置为白色将防止出现这种情况


这对我来说是可行的。将其放置在推送新ViewController的功能中。以下功能也可以工作,并使导航栏保持透明:


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

这在Swift中对我有效

didfishlaunchwithoptions
方法上的
AppDelegate
中,我设置了以下内容:

UIApplication.shared.windows.first?.backgroundColor = .white

这适用于我在iOS 13上使用的亮主题和暗主题,也适用于较旧的iOS版本

将以下代码添加到AppDelegate到
应用程序(didFinishLaunchingWithOptions)
方法:

if #available(iOS 13.0, *) {
    window?.backgroundColor = UIColor.systemBackground
} else {
    window?.backgroundColor = UIColor.white
}

对于那些已经实现了tabBar并希望nav和tabBar都保持半透明的人,在处理了两年痛苦的“推送时tabBar快照”解决方案后,我找到了一个简单的解决方案

诀窍在于:

  • 在选项卡栏上设置clear backgroundView,这会导致视图控制器的布局不同
  • 在第一个按钮下方设置新的模糊效果视图
  • 将模糊视图约束到选项卡栏(UIView)
  • 在我使用tabBar的快照并将tabBar的alpha设置为0之前,这会导致不必要的safeLayoutGuide偏移。由于这个解决方案现在可以访问任何私有变量,我希望这是绿色的,可以转到AppStore(我还没有到那里)

    在UITabBarController的viewDidLoad中,我设置了以下内容:

    tabBar.backgroundImage = UIImage()
    let blurView = UIVisualEffectView()
    blurView.effect = UIBlurEffect(style: .systemChromeMaterial)
    blurView.frame = tabBar.bounds
    blurView.translatesAutoresizingMaskIntoConstraints = false
    blurView.isUserInteractionEnabled = false
    tabBar.insertSubview(blurView, belowSubview: tabBar.subviews.first!)
    let leadingConstraint = blurView.leadingAnchor.constraint(equalTo: tabBar.leadingAnchor, constant: 0)
    let trailingConstraint = blurView.trailingAnchor.constraint(equalTo: tabBar.trailingAnchor, constant: 0)
    let topConstraint = blurView.topAnchor.constraint(equalTo: tabBar.topAnchor, constant: 0)
    let bottomConstraint = blurView.bottomAnchor.constraint(equalTo: tabBar.bottomAnchor, constant: 0)
    NSLayoutConstraint.activate([leadingConstraint, trailingConstraint, topConstraint, bottomConstraint])
    
    或:


    如果您不需要半透明的导航栏,您的解决方案就可以了。有一种更简单的方法可以获取
    背景视图<代码>[self.toolbar valueForKey:@“\u backgroundView”]
    。请注意,这是一个私有API,但我想你不会被苹果抓到,因为
    \u backgroundView
    只是一个通用名称。这个答案告诉我我需要做什么。在我的例子中,这就像在interface builder中取消选中UIToolbar上的半透明选项一样简单。您将其放置在何处?在主视图控制器的ViewDidLoad方法中,在ViewDidAppari中添加,我认为这实际上是正确的答案。
    navigationController.view.backgroundColor=.white
    在iOS 11上不再工作。@Annjawn,
    navigationController.view.backgroundColor=.white
    在iOS 12上工作。从导航栏中删除半透明不能用于n的情况
    UIApplication.shared.windows.first?.backgroundColor = .white
    
    if #available(iOS 13.0, *) {
        window?.backgroundColor = UIColor.systemBackground
    } else {
        window?.backgroundColor = UIColor.white
    }
    
    tabBar.backgroundImage = UIImage()
    let blurView = UIVisualEffectView()
    blurView.effect = UIBlurEffect(style: .systemChromeMaterial)
    blurView.frame = tabBar.bounds
    blurView.translatesAutoresizingMaskIntoConstraints = false
    blurView.isUserInteractionEnabled = false
    tabBar.insertSubview(blurView, belowSubview: tabBar.subviews.first!)
    let leadingConstraint = blurView.leadingAnchor.constraint(equalTo: tabBar.leadingAnchor, constant: 0)
    let trailingConstraint = blurView.trailingAnchor.constraint(equalTo: tabBar.trailingAnchor, constant: 0)
    let topConstraint = blurView.topAnchor.constraint(equalTo: tabBar.topAnchor, constant: 0)
    let bottomConstraint = blurView.bottomAnchor.constraint(equalTo: tabBar.bottomAnchor, constant: 0)
    NSLayoutConstraint.activate([leadingConstraint, trailingConstraint, topConstraint, bottomConstraint])
    
    //Setting background image to empty image to prevent a bug under top right navigation bar corner
    tabBar.backgroundImage = UIImage()
    //As that turns of the blur effect I am adding a new view imitating the same
    let blurView = UIVisualEffectView()
    blurView.effect = UIBlurEffect(style: .systemChromeMaterial)
    blurView.frame = tabBar.bounds
    blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    blurView.isUserInteractionEnabled = false
    tabBar.insertSubview(blurView, belowSubview: tabBar.subviews.first!)