7

I want to implement night mode in my APP (manually switch day and night mode), and I learned that I can use UiModeManager.setNightMode() and add some resources like values-night and drawable-night to archive it.

In document, before setNightMode(), we need to enableCarMode().

Using code like below can work, but problem appeared.

UiModeManager uiManager = (UiModeManager) getSystemService(Context.UI_MODE_SERVICE);
if (isNightMode) {
    uiManager.enableCarMode(0);
    uiManager.setNightMode(UiModeManager.MODE_NIGHT_YES);
} else {
    uiManager.disableCarMode(0);
    uiManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
}

It shows a notification to allow user to exit car mode.

enter image description here

Do you have any idea to disable this notification?

Or these just means it is not the best way to implement android night mode. And enabling car mode would make any strange difference to my APP or my phone?

PS: I wonder that why we need to enable car mode before setting night mode. Is there some deep consideration in this?

PPS: I already know that I can change theme to switch day and night mode. It needs to call this.recreate() and causes screen to flicker for a second.

PPPS: If UiModeManager.setNightMode and change theme are neither best way to implement night mode, what else choice do I have?

Edit:

Method 1: UiModeManager.setNightMode

enter image description here

Method 2: change theme

enter image description here

Edit again:

I think my idea was wrong. It is meaningless to disable the notification, but allow the car mode.

All I want is to implement night mode like Method 1, without setting something like desk or car mode, without showing flicker.

Finally

Using UiModeManager.setNightMode and enabling car mode are not the good way to implement night mode. Because it makes some effect in Android 5.0 and above.

When car mode is enabled and APP is running, I pressed home button, something strange happened (Test in nexus 7 Android 5.1.1). As the picture showed below:

Launch Android Auto

Look for the Android Auto button on your car's display to start

enter image description here

Unfortunately, UiModeManager.setNightMode can't be used unless car mode is needed.

Except car mode is enabled, the result is perfect and for developers it can just make some folders like drawable-night and values-night without change too much code. While mode is changed, it sends broadcast and switches the system configuration to the appropriate UI mode.

Although there are so many benefits, it is the wrong way to night mode.

I still wonder why car mode and night mode is combined so closely.

Community
  • 1
  • 1
Ellie Zou
  • 2,021
  • 2
  • 16
  • 21

2 Answers2

7

Thanks to NightModeHelper, I complete this feature.

In MainActivity.onCreate(), initialize the NightModeHelper.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mNightModeHelper = new NightModeHelper(this, R.style.Theme_Idxyer_NoActionBar);
}

And in somewhere you need to switch mode, add below line.

mNightModeHelper.toggle();

Also, values-night having color.xml will be needed.

All this can work like change theme method, showing flicker.

If you do not like flicker, you can try to setContentView(R.layout.main) and init views again. Don't forget to delete activity.recreate() in NightModeHelper class.

But if MainActivity contains fragment, you need to add fragment again, and fragment would flicker.

You can check demo in Github for source code.

----Edit-----

In Android Support Library 23.2 and above, Night Mode is official supported.

Ellie Zou
  • 2,021
  • 2
  • 16
  • 21
-1

The docs for setNightMode explicitly indicate that it only works when in Dock mode or in Car mode.

If you can just "change theme", however (I don't know how to do this), and then use Activity#recreate(), shouldn't you get similar results to what you're doing now? The docs for #recreate() state:

Cause this Activity to be recreated with a new instance. This results in essentially the same flow as when the Activity is created due to a configuration change -- the current instance will go through its lifecycle to onDestroy() and a new instance then created after it.

When a config change occurs, activities go through the full lifecycle (onPause --> onStop --> onDestroy --> onCreate --> onStart --> onResume), so it shouldn't be generating more or less flicker than switching to night mode using the config change mechanism.

Fabian Tamp
  • 4,416
  • 2
  • 26
  • 42
  • Can you have a look on my edit ? There are two gifs to show the difference between `setNightMode` and `change theme` – Ellie Zou Aug 11 '15 at 07:19
  • `change theme` means define two themes in styles.xml, and switch and save the theme id, then `Activity.recreate()` to take effect. And in activity `setTheme(themeId)` before `setContentView`. – Ellie Zou Aug 11 '15 at 07:25
  • Oh, ok. Thanks for the info. – Fabian Tamp Aug 11 '15 at 11:31
  • 1
    "The docs for setNightMode explicitly..." is now "Starting in API 23, changes to night mode are always effective." – steven smith May 25 '18 at 16:57