如何在Xamarin.Forms中检查暗模式

Bra*_*ick 2 xamarin.ios xamarin.android xamarin.forms

现在,iOS 13Android Q允许用户在操作系统级别启用暗模式,如何在Xamarin.Forms中进行检查?

我已经在Xamarin.Forms项目中创建了此文件,但不确定如何从Xamarin.iOS和Xamarin.Android中检索值。

IEnvironment.cs

using System.Threading.Tasks;

namespace MyNamespace
{
    public interface IEnvironment
    {
        Task<Theme> GetOperatingSystemTheme();
    }

    public enum Theme { Light, Dark }
}
Run Code Online (Sandbox Code Playgroud)

应用程式

using Xamarin.Forms;

namespace MyNamespace
{
    public App : Application
    {
        // ...

        protected override async void OnStart()
        {
            base.OnStart();

            Theme theme = await DependencyService.Get<IEnvironment>().GetOperatingSystemTheme();

            SetTheme(theme);
        }

        protected override async void OnResume()
        {
            base.OnResume();

            Theme theme = await DependencyService.Get<IEnvironment>().GetOperatingSystemTheme();

            SetTheme(theme);
        }

        void SetTheme(Theme theme)
        {
            //Handle Light Theme & Dark Theme
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

Lit*_*Dev 11

截至 2020 年 4 月的更新:

不再需要使用特定于平台的服务来检查 Xamarin.Forms 中的亮/暗模式。

我们现在可以通过以下方式直接获取当前主题:

OSAppTheme currentTheme = Application.Current.RequestedTheme;
Run Code Online (Sandbox Code Playgroud)

其中该RequestedTheme属性返回一个OSAppTheme枚举成员:UnspecifiedDark、 或Light

有关详细信息:请参阅文档更新的 Xamarin.Forms Application.cs 代码

  • 在 XAML 中,有很棒的 AppThemeBinding 可用于定义深色和浅色主题的 UI 值。在样式中使用,它是一个强大的工具。[https://devblogs.microsoft.com/xamarin/app-themes-xamarin-forms/](https://devblogs.microsoft.com/xamarin/app-themes-xamarin-forms/) (2认同)

Bra*_*ick 6

我们可以使用Xamarin.Forms依赖项服务从iOS和Android访问特定于平台的代码。

我在此博客文章中对此进行了更深入的介绍:https : //codetraveler.io/2019/09/10/check-for-dark-mode-in-xamarin-forms/

Xamarin.Forms代码

环境

using System.Threading.Tasks;

namespace MyNamespace
{
    public interface IEnvironment
    {
        Task<Theme> GetOperatingSystemTheme();
    }

    public enum Theme { Light, Dark }
}
Run Code Online (Sandbox Code Playgroud)

应用程式

using Xamarin.Forms;

namespace MyNamespace
{
    public App : Application
    {
        // ...

        protected override async void OnStart()
        {
            base.OnStart();

            Theme theme = await DependencyService.Get<IEnvironment>().GetOperatingSystemTheme();

            SetTheme(theme);
        }

        protected override async void OnResume()
        {
            base.OnResume();

            Theme theme = await DependencyService.Get<IEnvironment>().GetOperatingSystemTheme();

            SetTheme(theme);
        }

        void SetTheme(Theme theme)
        {
            //Handle Light Theme & Dark Theme
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

Xamarin.iOS

using System;
using UIKit;
using Xamarin.Forms;
using MyNamespace;
using MyNamespace.iOS;

[assembly: Dependency(typeof(Environment_iOS))]
namespace MyNamespace.iOS
{
    public class Environment_iOS : IEnvironment
    {
        public async Task<Theme> GetOperatingSystemTheme()
        {
            //Ensure the current device is running 12.0 or higher, because `TraitCollection.UserInterfaceStyle` was introduced in iOS 12.0
            if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
            {
                var currentUIViewController = await GetVisibleViewController();

                var userInterfaceStyle = currentUIViewController.TraitCollection.UserInterfaceStyle;

                switch (userInterfaceStyle)
                {
                    case UIUserInterfaceStyle.Light:
                        return Theme.Light;
                    case UIUserInterfaceStyle.Dark:
                        return Theme.Dark;
                    default:
                        throw new NotSupportedException($"UIUserInterfaceStyle {userInterfaceStyle} not supported");
                }
            }
            else
            {
                return Theme.Light;
            }
        }

        static Task<UIViewController> GetVisibleViewController()
        {
            // UIApplication.SharedApplication can only be referenced on by Main Thread, so we'll use Device.InvokeOnMainThreadAsync which was introduced in Xamarin.Forms v4.2.0
            return Device.InvokeOnMainThreadAsync(() =>
            {
                var rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;

                switch (rootController.PresentedViewController)
                {
                    case UINavigationController navigationController:
                        return navigationController.TopViewController;

                    case UITabBarController tabBarController:
                        return tabBarController.SelectedViewController;

                    case null:
                        return rootController;

                    default:
                        return rootController.PresentedViewController;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Xamarin.Android

using System;
using System.Threading.Tasks;
using Android.Content.Res;
using Plugin.CurrentActivity;
using Xamarin.Forms;

using MyNamespace;
using MyNamespace.Android;

[assembly: Dependency(typeof(Environment_Android))]
namespace MyNamespace.Android
{
    public class Environment_Android : IEnvironment
    {
        public Task<Theme> GetOperatingSystemTheme()
        {
            //Ensure the device is running Android Froyo or higher because UIMode was added in Android Froyo, API 8.0
            if(Build.VERSION.SdkInt >= BuildVersionCodes.Froyo)
            {
                var uiModeFlags = CrossCurrentActivity.Current.AppContext.Resources.Configuration.UiMode & UiMode.NightMask;

                switch(uiModeFlags)
                {
                    case UiMode.NightYes:
                        return Task.FromResult(Theme.Dark);

                    case UiMode.NightNo:
                        return Task.FromResult(Theme.Light);

                    default:
                        throw new NotSupportedException($"UiMode {uiModeFlags} not supported");
                }
            }
            else
            {
                return Task.FromResult(Theme.Light);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)