简体   繁体   English

升级到 Xcode 5.1 和 iOS 7.1 后,segue 转换期间导航栏上的暗影

[英]Dark shadow on navigation bar during segue transition after upgrading to Xcode 5.1 and iOS 7.1

When I am navigating back & forth between parent and child controllers in a master - detail navigation controller, i see a dark shadow on the right side of navigation bar at top.当我在主 - 细节导航控制器中的父控制器和子控制器之间来回导航时,我在顶部导航栏的右侧看到一个暗影。 It started after I upgraded to Xcode 5.1.它在我升级到 Xcode 5.1 后开始。 It feels rough and distracting.感觉粗糙和分散注意力。 How can I get rid of it?我怎样才能摆脱它?

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

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

self.navigationController.navigationBar.translucent = NO; 

对于较新的 Swift 版本:

navigationController?.navigationBar.isTranslucent = false

nonamelive's answer is perfect. nonamelive的答案是完美的。 To achieve the same thing in Interface Builder AND STILL KEEP TRANSLUCENCY , select the navigation controller and set a user defined runtime attribute view.backgroundColor as shown in the screenshot (in the Identity Inspector).要在 Interface Builder 中实现相同的操作并保持 TRANSLUCENCY ,请选择导航控制器并设置用户定义的运行时属性view.backgroundColor如屏幕截图(在身份检查器中)所示。 Repeat for all navigation controllers that show this problem.对显示此问题的所有导航控制器重复此操作。

It seems that this whole problem occurs because the black color (or actually, no color) of UINavigationController is leaking through at the time CoreGraphics snapshots it at animation begin.似乎整个问题的发生是因为 UINavigationController 的黑色(或实际上没有颜色)在 CoreGraphics 在动画开始时对其进行快照时泄漏。 So, setting it to white will prevent that.因此,将其设置为白色将防止出现这种情况。

Identity Inspector -> 用户定义的运行时属性

This seems to be a bug that was introduced in iOS 7.1.这似乎是 iOS 7.1 中引入的一个错误。 In my case it is caused by a UIToolbar placed directly below the navigation bar.在我的情况下,它是由直接放置在导航栏下方的 UIToolbar 引起的。 The dark shadow also appears in the translucent tab bar.黑色阴影也出现在半透明标签栏中。

The shadow seems to be caused by the background view of the UIToolbar.阴影似乎是由 UIToolbar 的背景视图引起的。 I now use this workaround in the view controller with the toolbar that hides the toolbar's background view during the transition:我现在在视图控制器中使用此解决方法,工具栏在转换期间隐藏工具栏的背景视图:

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

This is the code for [UIView findViewRecursively:]这是[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

I filed this Radar: http://openradar.appspot.com/16418845我提交了这个雷达: http : //openradar.appspot.com/16418845

It seems to happen with any bar (TabBar or ToolBar) that is translucent.任何半透明的栏(TabBar 或 ToolBar)似乎都会发生这种情况。
So one way to fix it is to set the _tabBar.translucent = NO;所以修复它的一种方法是设置_tabBar.translucent = NO; (in my case). (就我而言)。 This prevents the undesired shadow under the top navigation bar while leaving the navigation bar translucent.这可以防止顶部导航栏下方出现不需要的阴影,同时使导航栏保持半透明。 Unfortunately the bottom bar is no longer translucent though.不幸的是,底部栏不再是半透明的。

It can be set back to translucent but all this has to happen after the whole pushing animation is finished thus switching this property is well noticeable.它可以设置回半透明,但所有这些都必须在整个推送动画完成后发生,因此切换此属性非常明显。

In case, however the bottom bar also has to be translucent and I don't want the user to see the change I resolved it with the following:但是,如果底部栏也必须是半透明的,并且我不希望用户看到更改,我使用以下方法解决了它:

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

Then in the viewDidAppear: I simply reverts that back:然后在viewDidAppear:我简单地将其还原:

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

There is just a little change in the appearance especially but it's barely noticeable and it's way better than having the shadow under the navigation bar.特别是外观上只有一点点变化,但几乎不明显,而且比导航栏下的阴影要好得多。

Hope it'll help others to keep bars translucent until Apple fix this behaviour as bars ARE meant to be hidden in some cases unlike it was suggested in other posts especially for the UITabBar希望它会帮助其他人保持条形半透明,直到 Apple 修复此行为,因为条形在某些情况下是隐藏的,这与其他帖子中特别是针对UITabBar建议不同

This works for me in Swift这在Swift 中对我有用

In AppDelegate on didFinishLaunchingWithOptions method, I set this:didFinishLaunchingWithOptions方法的AppDelegate ,我设置了这个:

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

This works for me on iOS 13 with both light and dark themes and also on older iOS versions.这对我来说适用于iOS 13 的浅色深色主题以及较旧的 iOS 版本。

Add the following code to the AppDelegate to the application(didFinishLaunchingWithOptions) method:将以下代码添加到application(didFinishLaunchingWithOptions)方法的application(didFinishLaunchingWithOptions)

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

Here is my variation...it requires much less code than tom's answer, and is more efficient.这是我的变体……它需要的代码比汤姆的答案少得多,而且效率更高。 This is IF you want a translucent navigation bar, and also want to fix that shadow problem.如果您想要一个半透明的导航栏,并且还想解决阴影问题,那就是这样。

In the source ViewController (that is embedded in the Navigation Controller)...在源 ViewController(嵌入在导航控制器中)中...

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

and

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

The result is the same as what Tom does (visually, to the end user), and is easier to implement.结果与 Tom 所做的相同(视觉上,对最终用户而言),并且更容易实现。 Hope this helps...希望这可以帮助...

self.navigationController!.navigationBar.translucent = false;

这对我有用,将它放在推送新 ViewController 的函数中

以下也有效并使导航栏保持透明:

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

While it's not the same as the stock iOS implementation, this is a nice way to fix the problem:虽然它与股票的 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;
    }];
}

You'll get a nice fade-in/fade-out animation of the tab bar.你会得到一个很好的标签栏淡入/淡出动画。 Add the code in the root UIViewController .在根UIViewController添加代码。

For those, who have implemented tabBar and want to have both nav and tab bar still translucent, I found an easy workaround after dealing with painful "tabBar snapshot while push" workaround for a two years.对于那些已经实现了 tabBar 并且希望导航栏和标签栏仍然半透明的人,在处理了两年痛苦的“tabBar 快照同时推送”解决方法后,我找到了一个简单的解决方法。

The trick is to:诀窍是:

  1. set clear backgroundView on the tab bar, that cause to layout the view controllers differently在选项卡栏上设置 clear backgroundView,这会导致视图控制器的布局不同
  2. set a new BlurEffect view below first button在第一个按钮下方设置一个新的 BlurEffect 视图
  3. constraint the blur view to tabBar (UIView)将模糊视图约束到 tabBar (UIView)

Before I was using a snapshot of the tabBar and was setting alpha of the tabBar to 0, but that cause unwanted safeLayoutGuide offsets.在我使用 tabBar 的快照并将 tabBar 的 alpha 设置为 0 之前,但这会导致不需要的 safeLayoutGuide 偏移。 As this solution does now access any private variables, I hope this is green to go to AppStore (I'm not yet there).由于此解决方案现在可以访问任何私有变量,因此我希望访问 AppStore 是绿色的(我还没有到那里)。

In viewDidLoad of my UITabBarController I set following:在我的 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])

or:或者:

//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!)

Or if you're using interface builder, you can just select Navigation Bar from your navigation controller and uncheck the Translucent checkbox between Style and Bar Tint in the Attributes Inspector to get rid of that weird effect -或者,如果您使用的是界面构建器,您只需从导航控制器中选择导航栏,然后在属性检查器中取消选中样式和条形色调之间的半透明复选框即可摆脱这种奇怪的效果 -

检查员

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM