如何通过编程启用夜间模式?

51

我正在寻找一种通过Android代码以编程方式启用夜间模式的方法:

public static void setNightMode(Context target, boolean state){

    UiModeManager uiManager = (UiModeManager) target.getSystemService(Context.UI_MODE_SERVICE);

    if (state) {
        //uiManager.enableCarMode(0);
        uiManager.setNightMode(UiModeManager.MODE_NIGHT_YES);
    } else {
        // uiManager.disableCarMode(0);
        uiManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
    }
}

我的屏幕上没有任何变化,夜间模式仍然被禁用。 根据这个链接

不需要启用carMode或deskMode。 我在Android Studio上有以下的logcat:

11-26 12:15:16.662 3823-3823/? D/UiModeManager: updateConfigurationLocked: mDockState=0; mCarMode=false; mNightMode=2; uiMode=33
11-26 12:15:26.802 3823-3823/? V/UiModeManager: updateLocked: null action, mDockState=0, category=null

尝试一下这个链接:https://dev59.com/Ao3da4cB1Zd3GeqP6vT2 - Munir
我想要在所有地方改变夜间模式,而不仅仅是在我的应用程序中。我不需要切换一些主题。 - Ilan
你有看过这个提示吗?“注意:在API 22及以下版本中,仅当设备启用汽车或桌面模式时,夜间模式的更改才会生效。从API 23开始,夜间模式的更改始终有效。” - Google
你能解决这个问题吗?我正在努力使用setNightMode,但在Android 10或11上无法实现。 - Ton
7个回答

92

最简单的解决方案

您可以通过以下方式启用/禁用应用程序的黑暗主题:

  1. 启用黑暗主题:

 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
  • 强制禁用黑暗主题:

  •  AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
    
  • 根据移动设备的暗黑模式设置应用主题,即如果启用了暗黑模式,则将主题设置为暗黑主题;否则使用默认主题,但这仅适用于安卓版本 Q(10)及以上

  •  AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
    

    注意:

    1. 你的应用程序/活动的基本主题应为

    "Theme.AppCompat.DayNight"

    例如:

    <style name="DarkTheme" parent="Theme.AppCompat.DayNight">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    
    1. 你的res文件夹名称应以-night结尾,这样可以为白天和黑夜主题设置不同的颜色和图像,例如

    drawable & drawable-night,
    values & values-night


    2
    如果我没有看错的话,我认为 OP 正在寻找一种可以在设备级别上切换夜间模式的方法。您的代码在应用程序级别上完美地运行。因为我正在寻找一种可以更改整个设备的方法,所以 UiManager 似乎是正确的类来实现这一点。 - Mackovich
    对我来说完美无缺! - Mark Delphi
    对我来说也完美运行! - yoonhok

    18

    请确保在 styles.xml 文件中将默认主题从 Theme.AppCompat.Light.DarkActionBar 更改为 Theme.AppCompat.DayNight.DarkActionBar,然后执行 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 以切换到夜间模式。我已经在APIv23(Android 6.0)及以上版本进行了测试,效果良好。 要获得更好的解释,请参见由Android提供的此代码实验室


    你好,Neeraj Sewani。我正在尝试设置一个应用程序,可以简单地切换整个设备的夜间模式值。我正在使用uiManager.setNightMode(UiModeManager.MODE_NIGHT_YES)或MODE_NIGHT_NO。但是我无法得到它。我是否还需要更改我的应用程序中的“默认主题”?我不介意我的应用程序如何显示。我只想更改设备的夜间模式。谢谢。 - Ton

    6
    这段代码对我而言完美地运作,但你可能需要重新启动应用程序。但请记住,这段代码不仅可以在应用程序中启用暗黑模式,还可以在整个系统中启用。
    public static void setNightMode(Context target , boolean state){
    
        UiModeManager uiManager = (UiModeManager) target.getSystemService(Context.UI_MODE_SERVICE);
    
        if (VERSION.SDK_INT <= 22) {
            uiManager.enableCarMode(0);
        }
        
        if (state) {
            uiManager.setNightMode(UiModeManager.MODE_NIGHT_YES);
        } else {
            uiManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
        }
    }
    

    这在安卓4.4上对我有效。


    3
    请注意,暗黑模式不是夜间模式。它们完全不同。DM在Android 10中引入,强制使用内置的黑白颜色,而NM是在早期版本中发布的,使用默认/自定义样式通常称为资源限定符。如果您想处理自己的自定义浅色/夜间样式,并且不依赖于Android内置的暗黑风格,则可以在themes.xml或style.xml中将forceDarkAllowed设置为false以避免冲突。
    要将应用程序模式更改为夜间模式,请使用AppCompatDelegate。
    // This will be the top level handling of theme
            AppCompatDelegate.setDefaultNightMode(
                if (userPrefModeIsNight)
                    AppCompatDelegate.MODE_NIGHT_YES
                else
                    AppCompatDelegate.MODE_NIGHT_NO)
    

    谢谢。现在我可以在白天(中午)开发安卓的深色主题了。 - undefined

    1
    int nightModeFlags =
    getContext().getResources().getConfiguration().uiMode &
    Configuration.UI_MODE_NIGHT_MASK;
    switch (nightModeFlags) {
    case Configuration.UI_MODE_NIGHT_YES:
         doStuff();
         break;
    
    case Configuration.UI_MODE_NIGHT_NO:
         doStuff();
         break;
    
    case Configuration.UI_MODE_NIGHT_UNDEFINED:
         doStuff();
         break;
    }
    

    你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

    1

    还有一件事:您的Activity需要扩展自AppCompatActivity。

    如果它扩展了普通的Activity,则调用AppCompatDelegate.setDefaultNightMode将不起作用。


    -1

    NightOwl 在 Android 上有自己的日/夜模式切换实现。使用 NightOwl 超级简单。以下是代码片段:

    在 Application 类中初始化 NightOwl,

    NightOwl.builder().defaultMode(0).create();
    

    在你的Activity类中调用三个方法:
    public class DemoActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // step1 before super.onCreate
            NightOwl.owlBeforeCreate(this);
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_demo);
    
            // step2 after setContentView
            NightOwl.owlAfterCreate(this);
    
            // write your code
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            // step3 onResume
            NightOwl.owlResume(this);
        }
    
    }
    

    随心所欲地在任何地方切换皮肤,

    View v = findViewById(R.id.button);
    v.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            NightOwl.owlNewDress(SettingActivity.this);
        }
    });
    

    Google的库将是最佳选择。 - Vlad

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接