調整APP亮度,並且最高不高於系統亮度實現方案

項目新需求,app亮度進行單獨調節,但是調整的最大亮度不能高於系統亮度,接到需求之後,就在考慮實現方案,大致想到了三種方案

  • 直接調整系統亮度

在app中直接調整系統亮度,保存當前系統亮度,然後在activity生命週期中監聽回到桌面(這裏可在Application中registerActivityLifecycleCallbacks來實現),回到桌面之後調整回原來的系統亮度,切回app的時候再設置成app本身設置的系統亮度。

  • 在DecorView外層添加view

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

如果錯誤,請指正~
更多關於技術相關的內容請關注博主公衆號–迷途程序猿
迷途程序猿

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章