在 iOS13 上更改状态栏颜色

Posted

技术标签:

【中文标题】在 iOS13 上更改状态栏颜色【英文标题】:Change status bar colour on iOS13 【发布时间】:2020-01-23 21:59:01 【问题描述】:

ios 13 之前,我可以使用以下代码更改状态栏颜色:

        UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
        if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
        
            statusBar.BackgroundColor = UIColor.Clear.FromHex(0x323232);
            statusBar.TintColor = UIColor.White;
            app.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
        

但是,在 iOS13 上,我收到以下运行时错误

Objective-C 抛出异常。名称:NSInternalInconsistencyException 原因:应用程序在 UIApplication 上调用了 -statusBar 或 -statusBarWindow:此代码必须更改,因为不再有状态栏或状态栏窗口。改为在窗口场景中使用 statusBarManager 对象。

知道如何在 iOS13 上更改状态栏吗?

编辑:只是要指出,这是针对 Xamarin 而不是针对 Swift。澄清重复标记。

【问题讨论】:

How to change the status bar background color and text color on iOS 13?的可能重复 @Mac 这是怎么重复的?这是为了 swift,这是为了 Xamarin 它不是重复的。这里需要 xamarin ios 的解决方案。似乎需要一种设置状态栏背景颜色的新方法。但是,从苹果文档中,没有更多关于如何使用UIStatusBarManager的细节。 错误是一样的,解决方法应该是一样的,你只需要将swift代码转换为C# Xamarin代码。也就是说,我做了一个快速测试,但 KeyWindow 总是无效的,所以那个欺骗帖子的答案失败了。 @jgoldberger-MSFT 说解决方案是相同的,只是因为错误相同,考虑到这里有两个框架,这似乎有点过于简化了。 【参考方案1】:

由于报错,需要在IOS 13中使用UIStatusBarManager

如果您已将 VS 更新到最新版本(Visual Studio 2019 版本 16.3.0/Visual Studio 2019 for Mac 版本 8.3 ),您可以按如下方式更改颜色:

UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Yellow;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);

否则以下方法可以使其工作。

UIView statusBar = new UIView(UIApplication.SharedApplication.StatusBarFrame);
statusBar.BackgroundColor = UIColor.Yellow;
UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);

如果视图未完全渲染,UIApplication.SharedApplication.KeyWindow 将返回 null。因此您可以在完全渲染后更改状态栏颜色。这是sample。

====================================更新=========== =======================

如果在Forms项目中,你可以试试AppDelegate.cs中的调用方法

public override void OnActivated(UIApplication uiApplication)

    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    
        // If VS has updated to the latest version , you can use StatusBarManager , else use the first line code
        // UIView statusBar = new UIView(UIApplication.SharedApplication.StatusBarFrame);
        UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
        statusBar.BackgroundColor = UIColor.Red;
        UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
    
    else
    
        UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
        if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
        
            statusBar.BackgroundColor = UIColor.Red;
            UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
        
    
    base.OnActivated(uiApplication);
 

注意:

不确定这个解决方案在AppDelegate.cs 中是否始终有效,最好在Controller.cs 的方法中调用,因为从 iOS 13 开始,Apple 已经修改了 AppDelegate 的架构并添加了 SceneDelegate 进行投影。

【讨论】:

尝试访问UIApplication.SharedApplication.Windows[0] 会引发索引超出范围错误 @DavidPilkington 你试试KeyWindow,它适用于我的项目。您可以显示在 project 中调用它的位置,AppDelegate / ViewDidLoad 方法将不起作用。也就是说,您不能直接在FinishedLaunchingViewDidLoad 中使用它,因为视图没有完全呈现。您应该在 ViewDidAppear 或其他一些事件中调用它,例如 Button click method 等。 UIApplication.SharedApplication.StatusBarFrame 将返回 CGRect。但在解决方案中,您正在尝试转换为 UIView。它会起作用吗?它是工作副本吗? @VasanthRavichandran 是的,它会返回CGRect。您之前的代码也转换为UIView,它会起作用。我将在答案中分享我的样本。 @JohnLivermore 如果在 AppDelegate.cs 中,则不会有 ViewDidAppear 。我的共享答案基于 Xamarin.iOS 项目。 ViewDidAppear 可以在 Controller 中调用。现在你是一个Forms项目,你可以调用AppDelegate.cs中的OnActivated方法。我会更新答案。【参考方案2】:

如果在 UIViewController 中的 ViewDidAppear 覆盖中使用,这也有效。我之前在 ViewWillAppear 中进行了测试,即使这样也太早了,不能有一个 KeyWindow 非空:

public override void ViewDidAppear(bool animated)

    base.ViewDidAppear(animated);
    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    
        //Obj-C: 
        // UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
        // statusBar.backgroundColor = [UIColor redColor];
        // [[UIApplication sharedApplication].keyWindow addSubview:statusBar];

        // Xamarin.iOS: 
        UIView statusBar = new UIView(UIApplication.SharedApplication.KeyWindow.WindowScene.StatusBarManager.StatusBarFrame);
        statusBar.BackgroundColor = UIColor.Red;
        UIApplication.SharedApplication.KeyWindow.AddSubview(statusBar);
    
    else
    
        UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView;
        if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:")))
        
            statusBar.BackgroundColor = UIColor.Red;
            statusBar.TintColor = UIColor.White;
            UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.BlackOpaque;
        
    

这与重复问题中提供的解决方案相同:https://***.com/a/58028658/2913599

【讨论】:

【参考方案3】:

请您尝试以下解决方案。在相同的情况下它对我来说效果很好

if (@available(iOS 13.0, *))             
            UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame];
            statusBar.backgroundColor = [UIColor redColor];
            [[UIApplication sharedApplication].keyWindow addSubview:statusBar];

         else 
            // Fallback on earlier versions
            UIView *statusBar=[[UIApplication sharedApplication] valueForKey:@"statusBar"];
            statusBar.backgroundColor = [UIColor redColor];
            [statusBar setNeedsDisplay];
        

【讨论】:

以上是关于在 iOS13 上更改状态栏颜色的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 13 中更改状态栏颜色? [复制]

如何在 iOS 7 上更改状态栏背景颜色和文本颜色?

iOS 状态栏更改颜色

如何在iOS 7上更改状态栏背景颜色和文本颜色? Warif Akhand Rishi

iOS 7隐藏导航栏时如何更改状态栏的颜色?

在 iOS 13 中停止更改状态栏