最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android夜間模式最佳實踐

 更新時間:2016年02月19日 14:53:39   作者:馬俊  
這篇文章主要介紹了Android夜間模式最佳實踐,在Android應(yīng)用普遍支持夜間模式的今天,如何優(yōu)雅地實現(xiàn)夜間模式?感興趣的小伙伴們可以參考一下

由于Android的設(shè)置中并沒有夜間模式的選項,對于喜歡睡前玩手機的用戶,只能簡單的調(diào)節(jié)手機屏幕亮度來改善體驗。目前越來越多的應(yīng)用開始把夜間模式加到自家應(yīng)用中,沒準不久google也會把這項功能添加到Android系統(tǒng)中吧。

業(yè)內(nèi)關(guān)于夜間模式的實現(xiàn),有兩種主流方案,各有其利弊,我較為推崇第三種方案:

1、通過切換theme來實現(xiàn)夜間模式。
2、通過資源id映射的方式來實現(xiàn)夜間模式。
3、通過修改uiMode來切換夜間模式。

值得一提的是,上面提到的幾種方案,都是資源內(nèi)嵌在Apk中的方案,像新浪微博那種需要通過下載方式實現(xiàn)的夜間模式方案,網(wǎng)上有很多介紹,這里不去討論。

下面簡要描述下幾種方案的實現(xiàn)原理:

一、通過切換theme來實現(xiàn)夜間模式

首先在attrs.xml中,為需要隨theme變化的內(nèi)容定義屬性

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <attr name="textColor" format="color|reference" />
  <attr name="mainBackground" format="color|reference" />
</resources>

其次在不同的theme中,對屬性設(shè)置不同的值,在styles.xml中定義theme如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!-- 默認 -->
  <style name="ThemeDefault" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="mainBackground">#ffffff</item>
    <item name="textColor">#000000</item>
  </style>
  <!-- 夜間 -->
  <style name="ThemeNight" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="mainBackground">#000000</item>
    <item name="textColor">#ffffff</item>
  </style>
</resources>

在布局文件中使用對應(yīng)的值,通過?attr/屬性名,來獲取不同theme對應(yīng)的值。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android="@+id/main_screen"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:background="?attr/mainBackground">
  <Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="改變Theme"
    android:onClick="changeTheme"
    android:textColor="?attr/textColor"/>
</LinearLayout>

在Activity中調(diào)用如下changeTheme方法,其中isNightMode為一個全局變量用來標記當前是否為夜間模式,在設(shè)置完theme后,還需要調(diào)用restartActivity或者setContentView重新刷新UI。

public void changeTheme() {
  if (isNightMode) {
    setTheme(R.style.ThemeDefault);
    isNightMode = false;
  } else {
    setTheme(R.style.ThemeNight);
    isNightMode = true;
  }
  setContentView(R.layout.activity_main);
}

到此即完成了一個夜間模式的簡單實現(xiàn),包括Google自家在內(nèi)的很多應(yīng)用都是采用此種方式實現(xiàn)夜間模式的,這應(yīng)該也是Android官方推薦的方式。

但這種方式有一些不足,規(guī)模較大的應(yīng)用,需要隨theme變化的屬性會很多,都需要逐一定義,有點麻煩,另外一個缺點是要使得新theme生效,一般需要restartActivity來切換UI,會導致切換主題時界面閃爍。

不過也可以通過調(diào)用如下updateTheme方法,只更新需要更新的部分,規(guī)避閃爍問題,只是需要寫上一堆updateTheme方法。

private void updateTheme() {
  TypedValue typedValue = new TypedValue();
  Resources.Theme theme = getTheme();
  theme.resolveAttribute(R.attr.textColor, typedValue, true);
  findViewById(R.id.button).setBackgroundColor(typedValue.data);
  theme.resolveAttribute(R.attr.mainBackground, typedValue, true);
  findViewById(R.id.main_screen).setBackgroundColor(typedValue.data);
}

二、通過資源id映射的方式實現(xiàn)夜間模式

通過id獲取資源時,先將其轉(zhuǎn)換為夜間模式對應(yīng)id,再通過Resources來獲取對應(yīng)的資源。

public static Drawable getDrawable(Context context, int id) {
  return context.getResources().getDrawable(getResId(id));
}

public static int getResId(int defaultResId) {
  if (!isNightMode()) {
    return defaultResId;
  }
  if (sResourceMap == null) {
    buildResourceMap();
  }
  int themedResId = sResourceMap.get(defaultResId);
  return themedResId == 0 ? defaultResId : themedResId;
}

這里是通過HashMap將白天模式的resId和夜間模式的resId來一一對應(yīng)起來的。

private static void buildResourceMap() {
  sResourceMap = new SparseIntArray();
  sResourceMap.put(R.drawable.common_background, R.drawable.common_background_night);
  // ...
}

這個方案簡單粗暴,麻煩的地方和第一種方案一樣:每次添加資源都需要建立映射關(guān)系,刷新UI的方式也與第一種方案類似,貌似今日頭條,網(wǎng)易新聞客戶端等主流新聞閱讀應(yīng)用都是通過這種方式實現(xiàn)的夜間模式。

三、通過修改uiMode來切換夜間模式

首先將獲取資源的地方統(tǒng)一起來,使用Application對應(yīng)的Resources,在Application的onCreate中調(diào)用ResourcesManager的init方法將其初始化。

public static void init(Context context) {
  sRes = context.getResources();
}


切換夜間模式時,通過更新uiMode來更新Resources的配置,系統(tǒng)會根據(jù)其uiMode讀取對應(yīng)night下的資源,同時在res中給夜間模式的資源添加-night后綴,比如values-night,drawable-night。

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);
}

至于Android的資源讀取,我們可以參考老羅的博客《Android應(yīng)用程序資源的查找過程》,分析看看資源是怎么被精準找到的。這種方法相對前兩種的好處就是資源添加非常簡單清晰,但是UI上的更新還是無法做到非常順滑的切換。

我是怎么找到第三種方案的?

在Android開發(fā)文檔中搜索night發(fā)現(xiàn)如下,可以通過UiModeManager來實現(xiàn)

night: Night time
notnight: Day time
Added 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 using UiModeManager. See Handling Runtime Changes for information about how this affects your application during runtime.

不幸的是必須在駕駛模式下才有效,那是不是打開駕駛模式再設(shè)置呢,實際上是不可行的,駕駛模式下系統(tǒng)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(), Settings.Secure.UI_NIGHT_MODE, mode);
  mNightMode = mode;
  updateLocked(0, 0);
}

boolean isDoingNightModeLocked() {
  return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
}

在 isDoingNightModeLocked中判斷了DockState和mCardMode的狀態(tài),如果滿足條件實際上只修改了mNightMode的值,繼續(xù)跟蹤updateLocked方法,可以看到在updateConfigurationLocked中更新了Configuration的uiMode。

讓我們轉(zhuǎn)向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可以直接設(shè)置,既然UiModeManager設(shè)置nightMode只改了Configuration的uiMode,那我們是不是可以直接改其uiMode呢?

實際上只需要上面一小段代碼就可以實現(xiàn)了,但如果不去查看UiModeManager的夜間模式的實現(xiàn),不會想到只需要更新Configuration的uiMode就可以了。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助。

相關(guān)文章

  • 詳解Android Service 使用時的注意事項

    詳解Android Service 使用時的注意事項

    這篇文章主要介紹了詳解Android Service 使用時的注意事項,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Android設(shè)計模式系列之單例模式

    Android設(shè)計模式系列之單例模式

    單例模式,可以說是GOF的23種設(shè)計模式中最簡單的一個。接下來通過本文給大家實例講解android設(shè)計模式系列之單例模式的相關(guān)知識,感興趣的朋友一起看看吧
    2016-09-09
  • Android 開發(fā)系統(tǒng)自帶語音模塊應(yīng)用

    Android 開發(fā)系統(tǒng)自帶語音模塊應(yīng)用

    本篇文章 主要介紹 Android 開發(fā)自帶語音模塊實例,在開發(fā)Android系統(tǒng)中會用到系統(tǒng)語音搜索模塊,這里給大家一個參考實例
    2016-07-07
  • Android Studio 下載視頻到本地

    Android Studio 下載視頻到本地

    這篇文章主要介紹了Android Studio 下載視頻到本地,利用GreenDao實現(xiàn)多線程斷點續(xù)傳,這樣的話,下次用戶再次下載時,將繼續(xù)上次數(shù)據(jù)庫的接著下載,這樣用戶體驗就會很好,也大大節(jié)省了成本.具體實現(xiàn)代碼大家參考下本文
    2018-03-03
  • Android編程之SMS讀取短信并保存到SQLite的方法

    Android編程之SMS讀取短信并保存到SQLite的方法

    這篇文章主要介紹了Android編程之SMS讀取短信并保存到SQLite的方法,涉及Android針對SMS短信及SQLite數(shù)據(jù)庫的相關(guān)操作技巧,需要的朋友可以參考下
    2015-11-11
  • Android實現(xiàn)基本功能的新聞應(yīng)用

    Android實現(xiàn)基本功能的新聞應(yīng)用

    這篇文章主要介紹了一個簡易功能的Android新聞應(yīng)用實現(xiàn)流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-12-12
  • Android學習筆記之ListView復(fù)用機制詳解

    Android學習筆記之ListView復(fù)用機制詳解

    本篇文章主要介紹了Android學習筆記之ListView復(fù)用機制詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Android Intent實現(xiàn)頁面跳轉(zhuǎn)的方法示例

    Android Intent實現(xiàn)頁面跳轉(zhuǎn)的方法示例

    本篇文章主要介紹了Android Intent實現(xiàn)頁面跳轉(zhuǎn)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android實現(xiàn)微信搖一搖功能

    Android實現(xiàn)微信搖一搖功能

    這篇文章主要為大家詳細介紹了Android實現(xiàn)微信搖一搖功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • Kotlin在Android工程中的應(yīng)用詳解

    Kotlin在Android工程中的應(yīng)用詳解

    這篇文章主要為大家詳細介紹了Kotlin在Android工程中的應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評論

剑阁县| 拜城县| 海原县| 龙州县| 枣强县| 牙克石市| 凤山县| 三亚市| 日土县| 前郭尔| 农安县| 体育| 灵寿县| 宕昌县| 玉门市| 嘉义县| 富蕴县| 梁平县| 罗田县| 平陆县| 九寨沟县| 崇仁县| 平罗县| 汝城县| 奈曼旗| 醴陵市| 达日县| 平和县| 邯郸县| 福州市| 隆德县| 岢岚县| 电白县| 织金县| 台南市| 繁昌县| 定陶县| 临朐县| 吴旗县| 天镇县| 疏勒县|