一、前言:
最近在做一個(gè)App的設(shè)置項(xiàng)巾陕,亮度調(diào)節(jié)讨跟。真正做時(shí)纪他,發(fā)現(xiàn)Android亮度調(diào)節(jié)比預(yù)想要復(fù)雜一些。其實(shí)目前網(wǎng)上已有不少這方面的資料晾匠,但有些博文具有一定誤導(dǎo)性茶袒。在此將這塊內(nèi)容按照自己理解整理一下。
整體上看凉馆,Android亮度調(diào)節(jié)分為三個(gè)層次薪寓,分別是:Android系統(tǒng)亮度調(diào)節(jié)、Android App亮度調(diào)節(jié)和Android當(dāng)前屏幕(Window)亮度調(diào)節(jié)澜共。
1.Android系統(tǒng)亮度調(diào)節(jié)
Android系統(tǒng)亮度調(diào)節(jié)全局性最高向叉,常見(jiàn)于系統(tǒng)設(shè)置中的亮度設(shè)置項(xiàng)。Android中提供了獲取和設(shè)置系統(tǒng)亮度值(“手動(dòng)模式下的亮度值”)的接口嗦董,具體如下:
// 獲取系統(tǒng)亮度
Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
// 設(shè)置系統(tǒng)亮度
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,systemBrightness);
其中母谎,需要注意的是,返回的亮度值是處于0-255之間的整型數(shù)值京革。
Android 2.1以后的系統(tǒng)中奇唤,系統(tǒng)亮度調(diào)節(jié)中新增了“自動(dòng)亮度”選項(xiàng)〈嫜拢“自動(dòng)亮度”是依據(jù)外界光源來(lái)自動(dòng)的改變系統(tǒng)亮度冻记,目前大部分手機(jī)中對(duì)“自動(dòng)亮度”還可以進(jìn)行小幅度的調(diào)節(jié)其值。與自動(dòng)亮度相對(duì)應(yīng)的是“手動(dòng)亮度”来惧,當(dāng)處于“手動(dòng)亮度”下冗栗,設(shè)置拖動(dòng)亮度進(jìn)度條會(huì)大幅度的改變Android系統(tǒng)亮度」┎螅“手動(dòng)亮度”和“自動(dòng)亮度”分別稱之為Android系統(tǒng)的“亮度模式”隅居。
與之相對(duì)應(yīng)的,Android系統(tǒng)中也提供了獲取和設(shè)置“亮度模式”的接口葛虐。
// 獲取系統(tǒng)亮度模式
Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE);</pre>
// 設(shè)置系統(tǒng)亮度模式
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, systemMode);</pre>
可是遺憾的是胎源,Android中并未提供處于“自動(dòng)亮度”模式下的亮度值接口。上面所說(shuō)的獲取系統(tǒng)亮度值接口實(shí)際上都是指“手動(dòng)亮度”模式下的亮度值屿脐。
一般而言涕蚤,通過(guò)手動(dòng)亮度值以及設(shè)置系統(tǒng)亮度模式接口,可以滿足常規(guī)的大部分針對(duì)Android系統(tǒng)亮度設(shè)置編碼需求的诵,以完成系統(tǒng)亮度調(diào)節(jié)万栅。
2.Android App亮度調(diào)節(jié)
與系統(tǒng)亮度不同的是,Android中并未直接提供針對(duì)于App層面的亮度調(diào)節(jié)方式西疤。因此烦粒,對(duì)于需要進(jìn)行App的亮度調(diào)節(jié),可以通過(guò)系統(tǒng)亮度調(diào)節(jié)或當(dāng)前屏幕的亮度調(diào)節(jié)方式間接來(lái)實(shí)現(xiàn)代赁。
3.Android當(dāng)前屏幕(Window)亮度調(diào)節(jié)
Android針對(duì)當(dāng)前屏幕(Window)提供了設(shè)置亮度的接口扰她,常見(jiàn)寫(xiě)法如下:
Window window = activity.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.screenBrightness = brightness;
window.setAttributes(lp);
其中兽掰,需要注意的是此處的brightness是一個(gè)0.0-1.0之間的一個(gè)float類型數(shù)值。
默認(rèn)情況下徒役,當(dāng)我們直接修改了系統(tǒng)亮度值后孽尽,當(dāng)前Window中是可以即時(shí)反應(yīng)出來(lái)亮度效果的,這是因?yàn)槟J(rèn)情況下廉涕,WindowManager.LayoutParams的screenBrightness的默認(rèn)值為WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE泻云。
即表示W(wǎng)indow沒(méi)有自己的亮度參數(shù),將依隨系統(tǒng)亮度效果的變化而變化狐蜕。這也就是我們最常見(jiàn)的:當(dāng)調(diào)整系統(tǒng)亮度后,所有Window都即時(shí)反應(yīng)出系統(tǒng)亮度設(shè)置效果卸夕。
當(dāng)時(shí)层释,實(shí)際項(xiàng)目中我們還會(huì)遇到此類需求:系統(tǒng)設(shè)置亮度時(shí)只針對(duì)當(dāng)前Window或App內(nèi)生效,而不影響到系統(tǒng)本身的亮度設(shè)置快集。
假設(shè)當(dāng)前Window內(nèi)有一個(gè)SeekBar贡羔,UI與系統(tǒng)亮度調(diào)節(jié)UI基本類似,用戶可以滑動(dòng)此SeekBar个初,使得當(dāng)前Window亮度即時(shí)發(fā)生變化乖寒,且不影響到系統(tǒng)亮度效果。如何實(shí)現(xiàn)呢院溺?
此時(shí)我們需要啟用WindowManager.LayoutParams的screenBrightness參數(shù)楣嘁,使之具有自動(dòng)的特定亮度值,設(shè)置此值后在當(dāng)前Window范圍內(nèi)珍逸,其將覆蓋掉系統(tǒng)亮度設(shè)置逐虚。
因此,有必要將用戶選擇的亮度值轉(zhuǎn)換為相應(yīng)的Window亮度值(為與系統(tǒng)亮度值相一致谆膳,假設(shè)SeekBar的最大值為255)叭爱。
// 根據(jù)亮度值修改當(dāng)前window亮度
public void changeAppBrightness(Context context, int brightness) {
Window window = ((Activity) context).getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
if (brightness == -1) {
lp.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
} else {
lp.screenBrightness = (brightness <= 0 ? 1 : brightness) / 255f;
}
window.setAttributes(lp);
}
其中,brightness形參為用戶選擇的亮度值漱病。
那么买雾,上述代碼中為什么有一個(gè)"brightness == -1"的判斷呢?在此主要是考慮到App設(shè)置項(xiàng)中可能出現(xiàn)的“跟隨系統(tǒng)亮度”或“恢復(fù)系統(tǒng)默認(rèn)亮度”此類設(shè)置杨帽,當(dāng)用戶進(jìn)行此類操作時(shí)漓穿,直接將screenBrightness參數(shù)還原成默認(rèn)參數(shù)值即可。因?yàn)橛汕拔拿枋觥白詣?dòng)亮度”模式下系統(tǒng)亮度值是不能直接得到的睦尽,那么當(dāng)系統(tǒng)處于“自動(dòng)亮度”模式下器净,此時(shí)brightness參數(shù)值將無(wú)法準(zhǔn)確確定,因此当凡,將screenBrightness參數(shù)還原成默認(rèn)參數(shù)值成為一個(gè)行之有效的方法山害。
4.Android App亮度調(diào)節(jié)可行方案分析
目前網(wǎng)上有不少博文中提到App亮度調(diào)節(jié)時(shí)纠俭,提出的方案是在App設(shè)置項(xiàng)中,首先記錄下設(shè)置之前的系統(tǒng)亮度值和亮度模式浪慌,用戶在App設(shè)置項(xiàng)進(jìn)行亮度調(diào)節(jié)時(shí)冤荆,直接修改系統(tǒng)亮度值,當(dāng)用戶退出此App权纤,或App至于后臺(tái)(如按下Home按鍵等)钓简,再將系統(tǒng)亮度還原。初看起來(lái)貌似一個(gè)可行的方案汹想。但是主要存在如下幾個(gè)問(wèn)題:
如何獲取到設(shè)置之前的系統(tǒng)亮度值和亮度模式(因?yàn)橹笤诖薃pp外部要恢復(fù)系統(tǒng)亮度值到此初始值)外邓?當(dāng)用戶每次進(jìn)入到設(shè)置頁(yè)時(shí)獲取古掏?嚴(yán)格意義上來(lái)說(shuō)损话,是沒(méi)法準(zhǔn)確記錄的。因?yàn)锳ndroid的用戶操作不可預(yù)知性槽唾,如進(jìn)入到設(shè)置頁(yè)丧枪,拖動(dòng)SeekBar設(shè)置了一個(gè)亮度值,此時(shí)直接修改了系統(tǒng)的亮度值庞萍,如果此時(shí)用戶在未將應(yīng)用至于后臺(tái)或未將應(yīng)用退出的情況下直接在App外部修改了系統(tǒng)亮度設(shè)置拧烦,如小米中可以通過(guò)下拉標(biāo)題欄,直接就可以設(shè)置系統(tǒng)亮度钝计。因此恋博,App亮度設(shè)置之前的系統(tǒng)亮度初始值獲取存在困難。
如何判斷用戶來(lái)到了App外部葵蒂?因?yàn)榇藭r(shí)需要恢復(fù)系統(tǒng)亮度設(shè)置到初始系統(tǒng)亮度交播。如用戶可以按下Home按鍵,長(zhǎng)按Home按鍵直接切換App秦士,直接Back按鍵等一步步退出此App,下拉標(biāo)題欄直接點(diǎn)擊其他App通知信息進(jìn)入到其他App永高,手機(jī)自動(dòng)鎖屏后解鎖時(shí)用戶直接進(jìn)入其他應(yīng)用等等隧土,此類操作場(chǎng)景也具有不可預(yù)知性,因此命爬,判斷用戶來(lái)到了App外部以恢復(fù)系統(tǒng)亮度到初始值的時(shí)機(jī)上也存在一定困難曹傀。
由此,App亮度調(diào)節(jié)方案推薦通過(guò)設(shè)置當(dāng)前屏幕(Window)方式進(jìn)行饲宛。
大致思路如下:用戶在設(shè)置項(xiàng)中進(jìn)行亮度調(diào)節(jié)時(shí)皆愉,調(diào)用changeAppBrightness()方法,將改變當(dāng)前屏幕(Window)的亮度,此時(shí)對(duì)系統(tǒng)亮度無(wú)任何影響幕庐,接下來(lái)存在的問(wèn)題終于要就集中于當(dāng)用戶來(lái)到本App其他Activity中久锥,如果使得剛剛設(shè)置的亮度值得以即時(shí)反應(yīng)出來(lái)。
當(dāng)用戶進(jìn)行亮度調(diào)節(jié)后异剥,將當(dāng)前亮度設(shè)置值保存起來(lái)(如保存到SharedPreferences中)瑟由,在基類Activity中的onResume方法中,可以取出SharedPreferences中的用戶所設(shè)置的App亮度值冤寿,然后changeAppBrightness()方法以實(shí)現(xiàn)每個(gè)當(dāng)前屏幕的亮度調(diào)節(jié)歹苦。
總體說(shuō)來(lái),通過(guò)設(shè)置當(dāng)前屏幕(Window)的方式來(lái)設(shè)置App亮度更加簡(jiǎn)單有效督怜。