Implement the night mode: do not need recreate and do not flash screen, night recreate
Callback customization through resource id ingThe ThemeChangeListener interface is used to handle daytime/nighttime mode switching.
In colors. xml under values
#3F51B5
#3b3b3b
#303F9F
#383838
#FF4081
#a72b55
#FF000000
#FFFFFF
#FFFFFF
#3b3b3b
ThemeManager needs a ThemeManager topic management class.
Public class ThemeManager {// The default value is the daytime mode private static ThemeMode mThemeMode = ThemeMode. DAY; // The topic mode listener private static List
MThemeChangeListenerList = new queue list <> (); // night resource cache, key: resource type, Value
Private static HashMap
> SCachedNightResrouces = new HashMap <> (); // The suffix of the resources in the nighttime mode. For example, the resource name in the Japanese mode is R. color. activity_bg, the night mode is: R. color. activity_bg_night private static final String RESOURCE_SUFFIX = "_ night";/*** ThemeMode: daytime mode and nighttime mode */public enum ThemeMode {DAY, NIGHT}/*** set topic mode ** @ param themeMode */public static void setThemeMode (ThemeMode themeMode) {if (mThemeMode! = ThemeMode) {thinkememode = themeMode; if (thinkemechangelistenerlist. size ()> 0) {for (OnThemeChangeListener listener: mThemeChangeListenerList) {listener. onThemeChanged () ;}}}/*** get the resId of the topic based on the resId in the passed daytime mode. Note: it must be the resId of the daytime mode ** @ param dayResId of the daytime mode * @ return resId of the corresponding topic. If it is the daytime mode, dayResId is obtained; otherwise, the night mode will get the maid */public static int getCurrentThemeRes (Context context, int dayResId) {if (getThemeMode () = ThemeMode. DAY) {return dayResId;} // Resource Name String entryName = context. getResources (). getResourceEntryName (dayResId); // Resource Type String typeName = context. getResources (). getResourceTypeName (dayResId); HashMap
CachedRes = sCachedNightResrouces. get (typeName); // get from the cache first. if any, return the id if (cachedRes = null) {cachedRes = new HashMap <> ();} integer resId = cachedRes. get (entryName + RESOURCE_SUFFIX); if (resId! = Null & resId! = 0) {return resId;} else {// If the cache does not Dynamically Retrieve the try according to the resource id {// use the resource name, resource type, the int value of the resource obtained by the package name is int nightResId = context. getResources (). getIdentifier (entryName + RESOURCE_SUFFIX, typeName, context. getPackageName (); // put it in the cache. cachedRes. put (entryName + RESOURCE_SUFFIX, nightResId); sCachedNightResrouces. put (typeName, cachedRes); return nightResId;} catch (Resources. notFoundException e) {e. printStackTrace ();}} Return 0;}/*** register ThemeChangeListener ** @ param listener */public static void registerThemeChangeListener (OnThemeChangeListener listener) {if (! MThemeChangeListenerList. contains (listener) {mThemeChangeListenerList. add (listener) ;}}/*** unregistered ThemeChangeListener ** @ param listener */public static void unregisterThemeChangeListener (OnThemeChangeListener listener) {if (mThemeChangeListenerList. contains (listener) {mThemeChangeListenerList. remove (listener) ;}}/*** get topic mode ** @ return */public static ThemeMode getThemeMode () {return mThemeMode ;} /*** topic mode switching listener */public interface OnThemeChangeListener {/*** callback during topic switching */void onThemeChanged ();}}
In activity_main.xml, you only need to write a button and give the root layout an id (because you need to change the background color of the root layout)
Find the button id and root layout id in MainActivity. java
Implemented in MainActivityOnThemeChangeListener interface, so that the callback method can be executed when the topic changes. ThenIn initTheme (), reset the color attribute values of the UI. Also, do not forgetRemove ThemeChangeListener from onDestroy.
Public class MainActivity extends AppCompatActivity implements ThemeManager. onThemeChangeListener {private TextView TV; private Button btn_theme; private RelativeLayout relativeLayout; private ActionBar supportActionBar; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); ThemeManager. registerThemeChangeListener (This); supportActionBar = getSupportActionBar (); btn_theme = (Button) findViewById (R. id. btn_theme); relativeLayout = (RelativeLayout) findViewById (R. id. relativeLayout); TV = (TextView) findViewById (R. id. TV); btn_theme.setOnClickListener (new View. onClickListener () {@ Override public void onClick (View v) {themanager. setThemeMode (themanager. getThemeMode () = ThemeManager. themeMode. DAY? ThemeManager. themeMode. NIGHT: themanager. themeMode. DAY) ;}}) ;}public void initTheme () {TV. setTextColor (getResources (). getColor (themanager. getCurrentThemeRes (MainActivity. this, R. color. textColor); btn_theme.setTextColor (getResources (). getColor (themanager. getCurrentThemeRes (MainActivity. this, R. color. textColor); relativeLayout. setBackgroundColor (getResources (). getColor (themanager. ge TCurrentThemeRes (MainActivity. this, R. color. backgroundColor); // set the title bar color if (supportActionBar! = Null) {supportActionBar. setBackgroundDrawable (new ColorDrawable (getResources (). getColor (themanager. getCurrentThemeRes (MainActivity. this, R. color. colorPrimary);} // set the status bar color if (Build. VERSION. SDK_INT> = Build. VERSION_CODES.LOLLIPOP) {Window window = getWindow (); Window. setStatusBarColor (getResources (). getColor (themanager. getCurrentThemeRes (MainActivity. this, R. color. colorPrimary) ;}}@ Override public void onThemeChanged () {initTheme () ;}@ Override protected void onDestroy () {super. onDestroy (); ThemeManager. unregisterThemeChangeListener (this );}}