Android夜間模式最佳實現
Android夜間模式最佳實現目前用戶量達到一定量后的應用都會有夜間模式的功能,目前網上主要有兩種實現方式:1、比較簡單的實現可以定義一組theme來設置不同的顏色值等; 2、需要在assets中定義同樣的一組資源,這種實現方式對于要求有一整套夜間模式的資源,同時在代碼中也需要做較大的處理,缺點在 android5.0開始對selector也不支持,同時assets下的.9圖片不能直接使用,需要先編譯后放入到assets。
在android開發文檔中搜索night發現如下,可以通過UiModeManager來實現
Configuration | Qualifier Values | Description |
---|---|---|
Night mode | night Notnight | night: Night timenotnight: Day timeAdded in API level 8.This can change during the life of your application if night mode is left in auto mode (default), in which case the mode changes based on the time of day. You can enable or disable this mode usingUiModeManager. See Handling Runtime Changes for information about how this affects your application during runtime. |
不幸的是必須在駕駛模式下才有效,那是不是打開駕駛模式再設置呢,實際上是不可行的,駕駛模式下UI有變動,這種情況是不可取的
/** * Sets the night mode. Changes to the night mode are only effective when * the car or desk mode is enabled on a device. * * The mode can be one of: * {@link #MODE_NIGHT_NO}- sets the device into notnight * mode. * {@link #MODE_NIGHT_YES} - sets the device into night mode. * {@link #MODE_NIGHT_AUTO} - automatic night/notnight switching * depending on the location and certain other sensors. */ public void setNightMode(int mode)
從源碼開始看起UiModeManagerService.java的setNightMode方法中
if (isDoingNightModeLocked() && mNightMode != mode) { Settings.Secure.putInt(getContext().getContentResolver(),s Settings.Secure.UI_NIGHT_MODE, mode); mNightMode = mode; updateLocked(0, 0); } boolean isDoingNightModeLocked() { return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED; }
在 isDoingNightModeLocked中判斷了DockState和mCardMode的狀態,如果滿足條件實際上只修改了mNightMode 的值,繼續跟蹤updateLocked方法,可以看到在updateConfigurationLocked中更新了Configuration的 uiMode
讓我們轉向Configuration的uiMode的描述
/** * Bit mask of the ui mode. Currently there are two fields: * The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the * device. They may be one of {@link #UI_MODE_TYPE_UNDEFINED}, * {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK}, * {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION}, * {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_MODE_TYPE_WATCH}. * * The {@link #UI_MODE_NIGHT_MASK} defines whether the screen * is in a special mode. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED}, * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}. */ public int uiMode;
uiMode為public可以直接設置,既然UiModeManager設置nightMode只改了Configuration的uiMode,那我們是不是可以直接改其uiMode呢
實際上只需要以下一小段代碼就可以實現了,但是如果不去查看UiModeManager的夜間模式的實現不會想到只需要更新Configuration的uiMode就可以了
public static void updateNightMode(boolean on) { DisplayMetrics dm = sRes.getDisplayMetrics(); Configuration config = sRes.getConfiguration(); config.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK; config.uiMode |= on ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO; sRes.updateConfiguration(config, dm); }
這里最好是將獲取資源的Resource由Application來初始化,所有資源統一獲取,
別忘了在res中給夜間模式的資源后綴添加-night,比如values-night,drawable-night
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!