C# 更改iOS13上的状态栏颜色

C# 更改iOS13上的状态栏颜色,c#,xamarin,xamarin.ios,ios13,C#,Xamarin,Xamarin.ios,Ios13,在iOS 13之前,我可以使用以下代码位更改状态栏的颜色: UIView statusBar = UIApplication.SharedApplication.ValueForKey(new NSString("statusBar")) as UIView; if (statusBar.RespondsToSelector(new ObjCRuntime.Selector("setBackgroundColor:"))) {

在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的。要澄清重复标记。

避免出错,您需要在IOS 13中使用

如果您已将VS更新至最新版本(Visual Studio 2019版本16.3.0/Visual Studio 2019,适用于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。因此,您可以在完全呈现后更改状态栏的颜色。这是你的电话号码

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

如果是在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开始,苹果修改了AppDelegate的架构,并将SceneDelegate添加到project中。

您可以尝试下面的解决方案吗。在同样的情况下,这对我来说很好

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

如果在UIViewController的ViewDidDisplay覆盖中使用,这也可以工作。我以前在ViewWillDisplay中测试过,即使是这样也太早了,无法将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;
        }
    }
}

这与重复问题中提供的解决方案相同:

可能重复@Mac这是一个重复吗?这是给swift的,这是给xamarin的,它不是重复的。这里需要一个xamarin ios的解决方案。似乎需要一种新的方式来设置状态栏的背景色。然而,从apple文档中,没有更多关于如何使用的细节。错误是一样的,解决方案应该是一样的,您只需将swift代码转换为C#Xamarin代码。这就是说,我做了一个快速测试,KeyWindow总是nuil,所以从那篇重复文章中得到的答案失败了。@jgoldberger MSFT说解决方案是一样的,只是因为错误是一样的,考虑到这里使用的两个框架,这似乎有点过于简化了。尝试访问
UIApplication.SharedApplication.Windows[0]
将索引抛出范围之外error@DavidPilkington您是否尝试过使用
KeyWindow
,它在我的项目中有效。您可以在项目中的
AppDelegate/ViewDidLoad
中显示在何处调用此方法将不起作用。也就是说,您不能在
FinishedLaunching
ViewDidLoad
中直接使用它,因为视图没有完全渲染。您应该在
viewdideappear
或其他一些事件(如按钮单击方法等)中调用它。UIApplication.SharedApplication.StatusBarFrame将返回CGRect。但在解决方案中,您正试图转换为UIView。行吗?是工作副本吗?@vasanfravichandran是的,它将返回
CGRect
。您以前的代码也将转换为
UIView
,它将正常工作。我将在回答中分享我的示例。@JohnLivermore如果在
AppDelegate.cs
中,将不会出现
viewdid
。我的共享答案基于一个Xamarin.iOS项目<可以在控制器中调用代码>视图显示。现在这里是一个表单项目,您可以在
AppDelegate.cs
中调用
OnActivated
方法。我会更新答案。