Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Night Mode Helper - Helps use utilise the night and notnight resource qualifiers without being in car or dock mode.
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.preference.PreferenceManager;
/**
* Night Mode Helper
*
* <p>Helps use utilise the night and notnight resource qualifiers without
* being in car or dock mode.
*
* <p>Implementation is simple. Add the follow line at the top of your
* activity's onCreate just after the super.onCreate(); The idea here
* is to do it before we create any views. So the new views will use
* the correct Configuration.
*
* <pre>
* mNightModeHelper = new NightModeHelper(this, R.style.AppTheme);
* </pre>
*
* You can now use your instance of NightModeHelper to control which mode
* you are in. You can choose to persist the current setting and hand
* it back to this class as the defaultUiMode, otherwise this is done
* for you automatically.
*
* <p>I'd suggest you setup your Theme as follows:
*
* <ul>
* <li>
* <b>res\values\styles.xml</b>
* <pre>&lt;style name=&quot;AppTheme&quot; parent=&quot;AppBaseTheme&quot;&gt;&lt;/style&gt;</pre>
* </li>
* <li>
* <b>res\values-night\styles.xml</b>
* <pre>&lt;style name=&quot;AppBaseTheme&quot; parent=&quot;@android:style/Theme.Holo&quot;&gt;&lt;/style&gt;</pre>
* </li>
* <li>
* <b>res\values-notnight\styles.xml</b>
* <pre>&lt;style name=&quot;AppBaseTheme&quot; parent=&quot;@android:style/Theme.Holo.Light&quot;&gt;&lt;/style&gt;</pre>
* </li>
* </ul>
*
*
* @author Simon Lightfoot <simon@demondevelopers.com>
*
*/
public class NightModeHelper
{
private static final String PREF_KEY = "nightModeState";
private static int sUiNightMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
private WeakReference<Activity> mActivity;
private SharedPreferences mPrefs;
/**
* Default behaviour is to automatically save the setting and restore it.
*/
public NightModeHelper(Activity activity, int theme)
{
int currentMode = (activity.getResources().getConfiguration()
.uiMode & Configuration.UI_MODE_NIGHT_MASK);
mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
init(activity, theme, mPrefs.getInt(PREF_KEY, currentMode));
}
/**
* If you don't want the autoSave feature and instead want to provide
* your own persisted storage for the mode, use the defaultUiMode for it.
*/
public NightModeHelper(Activity activity, int theme, int defaultUiMode)
{
init(activity, theme, defaultUiMode);
}
private void init(Activity activity, int theme, int defaultUiMode)
{
mActivity = new WeakReference<Activity>(activity);
if(sUiNightMode == Configuration.UI_MODE_NIGHT_UNDEFINED){
sUiNightMode = defaultUiMode;
}
updateConfig(sUiNightMode);
// This may seem pointless but it forces the Theme to be reloaded
// with new styles that would change due to new Configuration.
activity.setTheme(theme);
}
private void updateConfig(int uiNightMode)
{
Activity activity = mActivity.get();
if(activity == null){
throw new IllegalStateException("Activity went away?");
}
Configuration newConfig = new Configuration(activity.getResources().getConfiguration());
newConfig.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
newConfig.uiMode |= uiNightMode;
activity.getResources().updateConfiguration(newConfig, null);
sUiNightMode = uiNightMode;
if(mPrefs != null){
mPrefs.edit()
.putInt(PREF_KEY, sUiNightMode)
.apply();
}
}
public static int getUiNightMode()
{
return sUiNightMode;
}
public void toggle()
{
if(sUiNightMode == Configuration.UI_MODE_NIGHT_YES){
notNight();
}
else{
night();
}
}
public void notNight()
{
updateConfig(Configuration.UI_MODE_NIGHT_NO);
mActivity.get().recreate();
}
public void night()
{
updateConfig(Configuration.UI_MODE_NIGHT_YES);
mActivity.get().recreate();
}
}
@AndroidDeveloperLB

This comment has been minimized.

Copy link

commented Jun 29, 2019

When does night mode kick in anyway?

@slightfoot

This comment has been minimized.

Copy link
Owner Author

commented Jul 5, 2019

When does night mode kick in anyway?

It starts when the sun-sets, and goes back to day when the sun-rises.

The Android Support Library / AndroidX now contains this code. So you would be better of using that.

@AndroidDeveloperLB

This comment has been minimized.

Copy link

commented Jul 5, 2019

Are you sure?
I saw on a video that they remove/deprecate it, and somewhere I saw that they did it due to poor performance.
BTW, since it's for the support library, from which Android version would it support to handle the night mode?

@slightfoot

This comment has been minimized.

Copy link
Owner Author

commented Jul 5, 2019

It was added in API level 8, which is Android 2.2 (Froyo) to the platform, and the support library I can't remember. You'll find more information by @chrisbanes on https://medium.com/androiddevelopers/appcompat-v23-2-daynight-d10f90c83e94

@AndroidDeveloperLB

This comment has been minimized.

Copy link

commented Jul 5, 2019

But back then it was used in very rare cases, in car-mode, or something...
Now it's a bit different, no?

@slightfoot

This comment has been minimized.

Copy link
Owner Author

commented Jul 5, 2019

Sure, but the support library and the code above overrides Car Mode.

@AndroidDeveloperLB

This comment has been minimized.

Copy link

commented Jul 6, 2019

And we now control when to trigger it, exactly, right?
Is it possible to also do it for the splash screen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.