項目新需求,app亮度進行單獨調節,但是調整的最大亮度不能高於系統亮度,接到需求之後,就在考慮實現方案,大致想到了三種方案
在app中直接調整系統亮度,保存當前系統亮度,然後在activity生命週期中監聽回到桌面(這裏可在Application中registerActivityLifecycleCallbacks來實現),回到桌面之後調整回原來的系統亮度,切回app的時候再設置成app本身設置的系統亮度。
對再BaseActivity中獲取當前window的getDecorView,然後在這個ViewGroup上添加一個ImageView,使用viewGroup的bringChildToFront(View view)方法將添加的ImageView設置到最外層,然後對這個ImageView 進行背景的透明度調節,核心代碼如下
mNightView = new ImageView(this);
ViewGroup root = (ViewGroup)getWindow().getDecorView();
Ln.d("添加view view = " + root.getChildCount());
root.addView(mNightView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
root.bringChildToFront(mNightView);
直接在BaseActivity中獲取窗口window,然後獲取window的WindowManager.LayoutParams,對其screenBrightness屬性進行調節,這個是大多數推薦的對單個app亮度進行調節的方式,我們今天主要講述的重點也就是這個
首先我們來分析下爲什麼我們選擇第三種,而不選擇前面兩種
首先來看第一種,第一種方案,貌似是一個很可行的方案,很容易滿足我們的需求,最大亮度只能是當前系統的最大亮度,而且一調整整個app都會調整,那爲什麼我們會不選擇呢?因爲這裏有一個設置系統亮度的步驟,我們如果想要設置系統的亮度,就涉及到一個問題,權限,android系統對非系統簽名的應用,在更改系統設置的時候是需要權限的,這一點在6.0之後尤爲嚴格,所以試想,當我們採用此方案的話,那麼在設置app亮度的時候首先要去請求權限,這時候就會出現彈框,這一步就已經很讓用戶煩躁了,就算用戶沒有厭煩情緒萬一用戶點擊了拒絕,那我們這個功能豈不就會失效了,因此這絕非一個好的實現方案
其次,我們來看第二種,這種方案我做過測試,如果我們只對主界面進行調整,那麼這種方案也是可以滿足我們的需求的,但是這裏也有有個漏洞,就是彈框,不管是Dialog,Popupwindow,DialogFragment,還是BottomSheetDialogFragment,這些彈框都是覆蓋在activity之上的,也就是說我們添加的那個ImageView是蓋不住這些彈框的,因此,當我們調整亮度到很低的時候,如果有彈框出來就會直接彈出高亮度的彈框,這顯然不是一個好的體驗,因此也pass了
接下來我們來說這篇文章的重點
首先我們需要獲取當前系統的亮度
private int getScreenBrightness(Context context) {
ContentResolver contentResolver = context.getContentResolver();
int defVal = 127;
return Settings.System.getInt(contentResolver,
Settings.System.SCREEN_BRIGHTNESS, defVal);
}
獲取到系統得最大亮度,這裏我們一定要獲取最大亮度而不是直接設置爲255,儘管官方說的系統最大亮度是255,但是我發現小米手機的亮度值是遠遠大於這個值的(小米8上面最大是1023)
private int getBrightnessMax() {
try {
Resources system = Resources.getSystem();
int resId = system.getIdentifier("config_screenBrightnessSettingMaximum", "integer", "android");
if (resId != 0) {
return system.getInteger(resId);
}
} catch (Exception ignore) {
}
return 255;
}
/**
* The screen backlight brightness between 0 and 255.
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
設置app亮度
private void setAppScreenBrightness(int birghtessValue) {
float systemBright = getScreenBrightness(this);
Window window = getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
float max = getBrightnessMax();
float ratio = systemBright / max;//系統的最大亮度就是當前window的最大亮度
float setbright = birghtessValue / 255.0f;
/**
* 當前window的亮度值應當是系統的最大亮度值和當前window真實亮度值相乘,
* 標示不能超過系統亮度,setbright 最大爲1
*/
lp.screenBrightness = setbright * ratio;
window.setAttributes(lp);
}
這裏還要注意一點,就是你的進度條最大進度設置爲255,如果進度太小的話 ,會出現當調整完系統亮度後,回到app的時候會出現明顯變暗的情況,我當初最大設置的是100,後面修改最大值之後就好了。
另外我們還需要監聽下系統亮度是否有變化,當有變化的時候我們也要同步修改app的亮度
監聽方法如下
* 監聽屏幕亮度變化
*/
private ContentObserver mBrightnessObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
updateBright();
}
};
我們只需要在BaseActivity的onResume()方法中註冊,在onDestory()中取消註冊就好了
@Override
protected void onResume() {
super.onResume();
getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS), true,
mBrightnessObserver);
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(
mBrightnessObserver);
}
如果錯誤,請指正~
更多關於技術相關的內容請關注博主公衆號–迷途程序猿