溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android編程實(shí)現(xiàn)夜間模式的方法小結(jié)

發(fā)布時(shí)間:2020-09-05 13:16:45 來(lái)源:腳本之家 閱讀:193 作者:AlexTam 欄目:移動(dòng)開(kāi)發(fā)

本文實(shí)例講述了Android編程實(shí)現(xiàn)夜間模式的方法。分享給大家供大家參考,具體如下:

隨著APP實(shí)現(xiàn)的功能越來(lái)越豐富, 看小說(shuō)看視頻上網(wǎng)等等, 現(xiàn)在不少人花在手機(jī)平板等移動(dòng)終端上的時(shí)間越來(lái)越長(zhǎng)了. 但手機(jī)和平板的屏幕并不像Kindle那類(lèi)電紙書(shū)的水墨屏那么耐看, 由于自發(fā)光的屏幕特性, 我們長(zhǎng)期盯著屏幕看容易眼睛酸痛疲倦, 因此各種護(hù)目模式, 夜間模式在移動(dòng)APP上得到廣泛應(yīng)用, 這的確也是一個(gè)貼心的小功能. 所以這次我們探討下幾種實(shí)現(xiàn)方式, 一起學(xué)習(xí)總結(jié)下:

1. 利用屏幕亮度

當(dāng)夜間使用手機(jī)等終端, 直接降低屏幕亮度, 能減少光線(xiàn)強(qiáng)度對(duì)眼鏡的刺激, 這也是最簡(jiǎn)單, 也相對(duì)有效的方式.

請(qǐng)先添加相應(yīng)權(quán)限:

<uses-permission android:name="android.permission.WRITE_SETTINGS"/>

通過(guò)設(shè)置屏幕亮度來(lái)實(shí)現(xiàn)的方法, 有兩種:

1) 只設(shè)置應(yīng)用程序內(nèi)的亮度

一般, Android里每個(gè)Activity對(duì)應(yīng)一個(gè)可視的界面, 針對(duì)每個(gè)Activity去設(shè)置亮度, 方法如下:

public static void setBrightness(Activity activity , float brightnessValue)
{
    WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
    if(brightnessValue > 1.0f)
    {
      lp.screenBrightness = 1.0f;
    }
    else if(brightnessValue <= 0.0f)
    {
      lp.screenBrightness = 0.0f;
    }
    else
    {
      lp.screenBrightness = brightnessValue;
    }
    activity.getWindow().setAttributes(lp);
}

這樣, 一個(gè)程序包含的所有Activity, 我們都要單獨(dú)去設(shè)置它的亮度, 雖說(shuō)可以封裝成工具類(lèi)去使用, 但前提是有沒(méi)有更好的方法呢? 請(qǐng)看第二種:

2) 設(shè)置手機(jī)系統(tǒng)的亮度(全局亮度)

這里, 我們直接在程序的某個(gè)Activity, 比如入口A(yíng)ctivity去設(shè)置整個(gè)手機(jī)的亮度. 由于已經(jīng)設(shè)置手機(jī)全局的亮度, 那么后面無(wú)論跳轉(zhuǎn)到哪個(gè)界面, 甚至退出程序, 手機(jī)的亮度依然是所設(shè)置的亮度. 這種方法相對(duì)第一種而言算是"一勞永逸". 但這里我們先要理清思路, 考慮好幾個(gè)點(diǎn):

打開(kāi)應(yīng)用后, 獲取手機(jī)原來(lái)的亮度值并保存它(可用于退出應(yīng)用后恢復(fù)正常亮度) --->  如果手機(jī)打開(kāi)自動(dòng)亮度調(diào)節(jié)則關(guān)閉自動(dòng)調(diào)節(jié), 然后設(shè)置合適的較低亮度 --->  將設(shè)置的亮度值應(yīng)用到手機(jī)中  --->  最后,退出應(yīng)用時(shí)利用保存的原亮度值恢復(fù)原來(lái)亮度, 并重新打開(kāi)手機(jī)的自動(dòng)亮度調(diào)節(jié).

接下來(lái), 貼上關(guān)鍵代碼:

首先是獲取手機(jī)屏幕亮度值:

/**
* 獲取當(dāng)前系統(tǒng)亮度
* <br>獲取失敗返回-1,獲取成功返回正常非負(fù)數(shù)<br>
* @param context
* @return
*/
public static int getSystemBrightness(Context context)
{
    int brightnessValue = -1;
    try
    {
      brightnessValue = Settings.System.
          getInt(context.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return brightnessValue;
}

保存, 直接放在SharePreference里面就好了, 相關(guān)代碼就不寫(xiě)了.
然后檢測(cè)手機(jī)是否打開(kāi)亮度自動(dòng)調(diào)節(jié)的開(kāi)關(guān):

/**
* 是否打開(kāi)自動(dòng)調(diào)節(jié)亮度
* @param contentResolver
* @return
*/
public static boolean isAutoBrightness(ContentResolver contentResolver)
{
    boolean autoBrightness = false;
    try
    {
      autoBrightness
          = Settings.System.getInt(contentResolver ,
              Settings.System.SCREEN_BRIGHTNESS_MODE)
          == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return autoBrightness;
}

如果打開(kāi), 就關(guān)閉:

/**
* 停止自動(dòng)調(diào)節(jié)亮度
* @param activity
*/
public static void closeAutoBrightness(Activity activity)
{
  Settings.System.putInt(activity.getContentResolver(),
    Settings.System.SCREEN_BRIGHTNESS_MODE,
    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
}

最后還會(huì)用到打開(kāi)亮度調(diào)節(jié):

public static void openAutoBrightness(Activity activity)
{
  Settings.System.putInt(activity.getContentResolver(),
    Settings.System.SCREEN_BRIGHTNESS_MODE,
    Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
}

關(guān)閉亮度調(diào)節(jié)后, 就設(shè)置亮度, 直接使用第一種方法中的相關(guān)代碼即可. 但因?yàn)橐獙⒃摿炼鹊脑O(shè)置應(yīng)用到全局, 所以需要將該亮度值保存到手機(jī)中:

/**
* 保存全局的亮度值設(shè)置
* @param contentResolver
* @param brightnessValue 亮度值
*/
public static void saveBrightness
(ContentResolver contentResolver , int brightnessValue)
{
    Uri uri = android.provider.Settings.System.getUriFor("screen_brightness");
    android.provider.Settings.System.putInt(contentResolver, "screen_brightness" , brightnessValue);
    contentResolver.notifyChange(uri, null);
}

這樣, 最終效果就OK了, 即使退出當(dāng)前應(yīng)用, 手機(jī)依然是所設(shè)置的較低亮度. 當(dāng)然, 退出應(yīng)用前應(yīng)當(dāng)恢復(fù)正常的亮度和設(shè)置, 于是就利用保存的亮度值重新設(shè)置, 然后將新的亮度值再次保存到手機(jī)中即可, 別忘了, 手機(jī)之前是打開(kāi)亮度自動(dòng)調(diào)節(jié)的話(huà), 還要重新打開(kāi)自動(dòng)調(diào)節(jié).

2. 自定義Theme.(最常用的方法)

自定義View, 相信很多人都很熟悉. 而自定義Theme跟這個(gè)類(lèi)似, 也是實(shí)現(xiàn)夜間模式最常用的方法, 因?yàn)樗恢箍梢詫?shí)現(xiàn)夜間模式, 還能實(shí)現(xiàn)常見(jiàn)的主題更換功能. 這里就不細(xì)說(shuō), 只講思路. 假設(shè)我們的應(yīng)用界面是白色背景, 黑色文字, 夜間模式就是黑色背景, 灰白色的文字. 這種夜間模式有別于第一種的調(diào)節(jié)亮度, 由于背景和內(nèi)容文字可以隨意的設(shè)置顏色和透明度, 這種夜間模式看起來(lái)更直觀(guān),也可以更舒服.

自定義Theme利用的是, 在XML中定義要用到的背景和文字顏色屬性, 比如:

<declare-styleable name="MyThemeAttrs">
  <attr name="activity_background" format="color" />
  <attr name="text_color" format="color" />
</declare-styleable>

然后在style.xml中創(chuàng)建自己的兩個(gè)主題(Theme), 比如默認(rèn)主題和夜間主題, 默認(rèn)主題中給activity_background屬性設(shè)為白色, text_color屬性設(shè)為黑色, 夜間主題則分別為黑色和灰白色. 在View的layout文件中, 給所用的背景View, 比如某個(gè)RelativeLayout的backgroundColor屬性設(shè)為"?activity_background", TextView的textColor設(shè)為"?text_color"即可. 當(dāng)然, 由于這是Theme, 在A(yíng)ctivity開(kāi)始初始化視圖前去應(yīng)用才能生效. 因此最好自己封裝一個(gè)主題工具類(lèi), 在A(yíng)ctivity的setContentView( ) 方法之前調(diào)用setTheme() 方法去設(shè)置主題.

3. WindowManager實(shí)現(xiàn)遮罩模式

這里, 我們應(yīng)當(dāng)明白一個(gè)概念, 當(dāng)不必深究, window(窗口). Android的設(shè)計(jì)理念中, 給幾乎每個(gè)顯示的組件都設(shè)置包含在一個(gè)window中. Activity也有它自己的window. 通過(guò)在window添加一層灰黑色有一定透明度的view, 使它看起來(lái)是屏幕變暗了, 當(dāng)然實(shí)際上手機(jī)的亮度是沒(méi)有變化的, 這種實(shí)現(xiàn), 可以叫"遮罩", 類(lèi)似相機(jī)拍照時(shí)在鏡頭套一層膜或者鏡片上去, 使呈現(xiàn)的效果有所不同. 但是這種方法, 也有不好的地方, 就是類(lèi)似上面說(shuō)的單獨(dú)在每個(gè)Activity去設(shè)置它的亮度. 這里每進(jìn)入一個(gè)界面就需要重新"套一層view"上去, 相對(duì)"一勞永逸"的方法而言, 顯得沒(méi)優(yōu)勢(shì). 那么直接上代碼:

WindowManager manager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.MATCH_PARENT,
    WindowManager.LayoutParams.TYPE_APPLICATION,
    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP;
params.y = 10;// 距離底部的距離是10像素 如果是 top 就是距離top是10像素
TextView tv = new TextView(this);
tv.setBackgroundColor(0x55000000);
manager.addView(tv,params);

代碼中, 通過(guò)WindowManager.LayoutParams的參數(shù)設(shè)置, 禁止所添加遮罩層的觸摸和聚焦. 這樣使得即使添上一層View, 也不會(huì)影響Activity視圖中的組件正常使用.

其實(shí)上面三種方法, 放在現(xiàn)在來(lái)看, 都不是新的技術(shù), 而網(wǎng)上我也看過(guò)很多相關(guān)的代碼, 這里這只是放在一起做個(gè)對(duì)比和總結(jié). 上面根據(jù)三種實(shí)現(xiàn)方法說(shuō)了各自的特點(diǎn), 綜合而言, 第一, 二種方法比較可取, 而究竟選擇第一還是第二種方法, 應(yīng)該看具體需求, 如果你的應(yīng)用只是簡(jiǎn)單的要求降低亮度, 不想修改太多的代碼, 那么第一種會(huì)比較適合; 如果希望有良好的體驗(yàn), 希望看起來(lái)更酷, 甚至還想添加其他的主題, 比如藍(lán)色, 綠色的主題等等, 那么無(wú)疑第二種是最好的選擇. 自定義屬性的廣泛應(yīng)用, 給我們實(shí)現(xiàn)更個(gè)性化的視覺(jué)效果(比如自定義組件, 自定義主題等)提供了便利.

更多關(guān)于A(yíng)ndroid相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Android開(kāi)發(fā)入門(mén)與進(jìn)階教程》、《Android調(diào)試技巧與常見(jiàn)問(wèn)題解決方法匯總》、《Android基本組件用法總結(jié)》、《Android視圖View技巧總結(jié)》、《Android布局layout技巧總結(jié)》及《Android控件用法總結(jié)》

希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI