Activity樣式 、狀態列透明的一些總結——你絕對想不到的

codeGoogle發表於2017-07-28

有關於Activity作為dialog全屏顯示,沉浸式狀態列及螢幕亮度問題的一次總結

需求:

  • 1.彈出一個全屏顯示的Dialog,裡面做了好多的邏輯處理,比如搶紅包,請求介面,比如動畫效果。

  • 2.通過某一事件改變當前佈局的背景顏色

效果圖:

Markdown
Markdown

分析:

    1. 如果碰到佈局和邏輯比較複雜的dialog,則建議用彈出activity作為一個dialog,因為生命週期及其API提供的比較多
    1. 實現全屏的dialog要設定主題
    1. 實現狀態列透明
    1. 設定亮度的問題

設定Activity透明度

Markdown
Markdown

  • 使用自定義主題,先看看自定義主題中需要用到的一些屬性設定說明

       <!-- 在此新增一種顏色值模式ARGB{xxxxxxxx},A{前兩位}表示Appha即透明度,取值為0-255 -->
          <style name="activity_DialogTransparent">
              <item name="android:windowBackground">@android:color/transparent</item>
              <item name="android:windowFullscreen">true</item>
              <item name="android:backgroundDimEnabled">true</item>
              <item name="android:backgroundDimAmount">0.2</item>
              <item name="android:windowIsTranslucent">true</item>
              <item name="android:layout_width">fill_parent</item>
              <item name="android:layout_height">fill_parent</item>
              <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item> <!--Activity切換動畫效果-->
          </style>複製程式碼

    定義好主題之後需要在Activity配置中進行對主題的引用!

    在程式碼中對窗體設定透明度灰度的方法
    設定透明度(這是窗體本身的透明度,非背景)

      WindowManager.LayoutParams windowLP = getWindow().getAttributes();
      windowLP.alpha = 0.5f;
      getWindow().setAttributes(windowLP);複製程式碼

    alpha在0.0f到1.0f之間。1.0完全不透明,0.0f完全透明

    設定灰度

      WindowManager.LayoutParams windowLP = getWindow().getAttributes();
      windowLP.dimAmount = 0.5f;
      getWindow().setAttributes(windowLP);
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);複製程式碼

    dimAmount在0.0f和1.0f之間,0.0f完全不暗,1.0f全暗

    這些設定對dialog對話方塊同樣也有效;

  • 在清單檔案中配置Activity時宣告

      android:theme="@android:style/Theme.Translucent" 複製程式碼

設定Activity/Application全屏

1.在程式碼中設定

   //無title    
   requestWindowFeature(Window.FEATURE_NO_TITLE);    
    //全屏    
   getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN);
   //此兩段程式碼必須設定在setContentView()方法之前
   setContentView(R.layout.main);  複製程式碼

2.在配置檔案中設定
在Activity的宣告中設定主題為全屏

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"複製程式碼

狀態列著色-透明狀態列

blog.csdn.net/androidstar…

從Android4.4開始,才可以實現狀態列著色,並且從5.0開始系統更加完善了這一功能,可直接在主題中設定

<item name="colorPrimaryDark">@color/colorPrimaryDark</item>複製程式碼

或者

getWindow().setStatusBarColor(color)複製程式碼

來實現,但畢竟4.4+的機器還有很大的佔比,所以就有必要尋求其它的解決方案。

第一種方案:

1、首先將手機手機狀態列透明化:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }複製程式碼

在相應的Activity或基類執行這段程式碼就ok了。

可見在4.4到5.0的系統、5.0及以上系統的處理方式有所不同

除了這種程式碼修改額方式外,還可以通過主題來修改,需要在values、values-v19、values-v21目錄下分別建立相應的主題:

//values
<style name="TranslucentTheme" parent="AppTheme">
</style>

//values-v19
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
</style>

//values-v21
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
</style>複製程式碼

給相應Activity或Application設定該主題就ok了。

兩種方式根據需求選擇就好了,到這裡我們就完成了第一步,將狀態列透明化了。

完成了第一步,我們開始給狀態列加上想要的色彩吧!

在values、values-v19目錄新增如下尺寸:

//values
<dimen name="padding_top">0dp</dimen>

//values-v19
<dimen name="padding_top">25dp</dimen>複製程式碼

關於25dp,在有些系統上可能有誤差,這裡不做討論!

2.1 頁面頂部使用Toolbar(或自定義title)
一般情況狀態列的顏色和Toolbar的顏色相同,既然狀態列透明化後,佈局頁面延伸到了狀態列,何不給Toolbar加上一個狀態列高度的頂部padding呢:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:paddingTop="@dimen/padding_top"
    android:theme="@style/AppTheme.AppBarOverlay" />複製程式碼

效果圖下:

Markdown
Markdown

第二種方案:

在方案一中,我們沒有使用android:fitsSystemWindows="true"屬性,而是將佈局延伸到狀態列來處理,這次我們使用android:fitsSystemWindows="true"屬性,不讓佈局延伸到狀態列,這時狀態列就是透明的,然後新增一個和狀態列高、寬相同的指定顏色View來覆蓋被透明化的狀態列。我們一步步來實現。

1、第一步還是先將狀態列透明化,方法同上。

2、在佈局檔案中新增android:fitsSystemWindows="true"屬性:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:title="第二種方案" />
</LinearLayout>複製程式碼

3、建立View並新增到狀態列:

private void addStatusBarView() {
        View view = new View(this);
        view.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                getStatusBarHeight(this));
        ViewGroup decorView = (ViewGroup) findViewById(android.R.id.content);
        decorView.addView(view, params);
    }複製程式碼

原理很簡單,但是要額外寫這些程式碼。。。最後看下效果:

Markdown
Markdown

第三種方案:

和方案二類似,同樣使用android:fitsSystemWindows="true"屬性,再修改佈局檔案的根佈局為需要的狀態列顏色,因根佈局的顏色被修改,所以你需要在裡邊多巢狀一層佈局,來指定介面的主背景色,比如白色等等,否則就和狀態列顏色一樣了。說起來有點抽象,還是看具體的例子吧:

1、先將狀態列透明化,方法同上。

2、修改佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff9900"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ff9900"
            android:theme="@style/AppTheme.AppBarOverlay"
            app:title="第三種方案" />
    </LinearLayout>
</RelativeLayout>複製程式碼

修改完了,看效果:

Markdown
Markdown

如果專案有幾十個介面,這樣的方式修改起來還是挺累的,你還要考慮各種巢狀問題。
後兩種方案的例子相對簡單,有興趣的話你可以嘗試更多的場景!
三種方式如何選擇,相信到這裡你應該有答案了吧,我個人更喜歡第一種!

有關於Activity螢幕亮度問題

/**
 * Android獲取並設定Activity的亮度
 * 此API只適合2.1以上版本
 */
public class ActivityUtils  {
    /**
     * 判斷是否開啟了自動亮度調節
     *
     * @param aContentResolver
     * @return
     */
    public static boolean isAutoBrightness(ContentResolver aContentResolver) {
        boolean automicBrightness = false;
        try {
            automicBrightness = Settings.System.getInt(aContentResolver,
                    Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        return automicBrightness;
    }

    /**
     * 獲取螢幕的亮度
     *
     * @param activity
     * @return
     */
    public static int getScreenBrightness(Activity activity) {
        int nowBrightnessValue = 0;
        ContentResolver resolver = activity.getContentResolver();
        try {
            nowBrightnessValue = android.provider.Settings.System.getInt(
                    resolver, Settings.System.SCREEN_BRIGHTNESS);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return nowBrightnessValue;
    }

    /**
     * 設定亮度
     *
     * @param activity
     * @param brightness
     */
    public static void setBrightness(Activity activity, int brightness) {
        // Settings.System.putInt(activity.getContentResolver(),
        // Settings.System.SCREEN_BRIGHTNESS_MODE,
        // Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f);
        activity.getWindow().setAttributes(lp);
    }

    /**
     * 停止自動亮度調節
     *
     * @param activity
     */
    public static void stopAutoBrightness(Activity activity) {
        Settings.System.putInt(activity.getContentResolver(),
                Settings.System.SCREEN_BRIGHTNESS_MODE,
                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
    }

    /**
     * 開啟亮度自動調節
     *
     * @param activity
     */
    public static void startAutoBrightness(Activity activity) {
        Settings.System.putInt(activity.getContentResolver(),
                Settings.System.SCREEN_BRIGHTNESS_MODE,
                Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
    }

    /**
     * 儲存亮度設定狀態
     *
     * @param resolver
     * @param brightness
     */
    public static void saveBrightness(ContentResolver resolver, int brightness) {
        Uri uri = android.provider.Settings.System
                .getUriFor("screen_brightness");
        android.provider.Settings.System.putInt(resolver, "screen_brightness",
                brightness);
        resolver.notifyChange(uri, null);
    }
}複製程式碼

注意以上只適用於2.1的版本。

可以通過seekBar改變其亮度:

/**
*   使用SeekBar進行亮度控制:
*/
private void detalSeekBar() {
        sSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,
                                          boolean fromUser) {
                LogUtil.e("yuyahao","progress:  "+progress);
                if (progress < 10) {
                } else {
                    messageTv.setText("activity當前亮度為: "+progress);
                    ActivityUtils.setBrightness(MyShowLightDialog.this, progress);
                    //ll_contentView.setBackgroundResource(ContextCompat.getColor(MainActivity.this,Color.parseColor("#"+getRandColorCode()));
                    ll_contentView.setBackgroundColor(Color.parseColor("#"+getRandColorCode()));
                }
            }
        });
        //獲取當前亮度的位置
//        int a =ActivityUtils.getScreenBrightness(this);
//        sSeekBar.setProgress(a);
    }複製程式碼

效果圖:

Markdown
Markdown

github專案的地址:

github.com/androidstar…

如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809   
微信公眾號:終端研發部

Markdown
Markdown

(歡迎關注學習和交流)

相關文章