天天看點

實作沉浸式的三種方式

首先說一下我對沉浸式狀态欄的了解,在4.4之前,狀态欄都是黑乎乎的,看起來很不美觀,在4.4之後可以将狀态欄設定成透明并和标題欄同一種顔色。以下是我總結的實作沉浸式的幾種方式。

第一種方式:使用系統API實作沉浸式

1.1、首先看布局檔案

添加android:fitsSystemWindows=”true”, android:clipToPadding=”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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="teststatusbar.com.xn.teststatusbar.MainActivity">

    <TextView
        android:background="@android:color/holo_blue_dark"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipToPadding="true"
        android:fitsSystemWindows="true"
        android:onClick="firstWay"
        android:text="第一種方式實作沉浸式狀态欄" />

</LinearLayout>
           

或者直接設定屬性:

<item name="android:statusBarColor">@color/system_bottom_nav_color</item>,
           

這個屬性是直接設定狀态欄的顔色,這個屬性是在style中設定的。或者直接用代碼來改變顔色,隻在5.0及以上才能起作用。

<item name="android:windowTranslucentStatus">true</item>
           

這個屬性就是設定狀态欄為透明,同樣在style檔案中來設定的,但是有個弊端就是狀态欄會往上移,是以标題欄的高度會減少,減少的高度為狀态欄的高度,大概是24dp。這時我們通過反射機制來動态增加高度,或者給Toolbar設定android:fitsSystemWindows=”true”,或者給最外層的容器設定這個屬性,這樣也可以将減少的高度補回來。

1.2、java代碼如下:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initStatusbar();
    }

    /**
     * 初始化狀态欄
     */
    private void initStatusbar() {
       //這裡是判斷目前的目标版本是否在4.4及以上,如果在4.4之上我們才設定沉浸式
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //透明狀态欄
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //透明導航欄
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }
}
           

效果如下:

實作沉浸式的三種方式

第二種方式:使用反射機制動态加載标題欄

思路是這樣的:先擷取到狀态欄的高度,再擷取到我們自定義的标題欄的高度,然後将我們的标題欄的高度設定為兩者之和,在這之前需要将我們原本的狀态欄設為透明。這樣就完成了我們的沉浸式狀态欄。

2.1:在布局檔案中定義好自定義的标題欄

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="teststatusbar.com.xn.teststatusbar.SecondActivity">

    <LinearLayout
        android:id="@+id/line"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="@android:color/holo_blue_dark">

        <TextView
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="第二種方式實作沉浸式狀态欄" />
    </LinearLayout>
</LinearLayout>
           

高度我們設定的80dp。

2.2、在java代碼中動态設定狀态欄的高度

public class SecondActivity extends AppCompatActivity {
    LinearLayout lin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        lin = (LinearLayout) findViewById(R.id.line);
        setStatus();
    }

    /**
     * 設定沉浸式狀态欄
     */
    private void setStatus() {
        //判斷是否是大于目前版本4.4,如果大于則實作沉浸式
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//标題欄透明
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//導航欄透明
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

            lin.post(new Runnable() {
                @Override
                public void run() {
                    final int statusheight = getLayoutHeight();
                    final int linHeight = lin.getHeight();
                    Log.e("statusheight linHeight", ""+statusheight+":"+linHeight);
                    ViewGroup.LayoutParams layoutParams = lin.getLayoutParams();
                    layoutParams.height = statusheight + linHeight;
                    lin.setLayoutParams(layoutParams);
                }
            });
        }
    }

    /**
     * 擷取狀态欄的高度
     *
     * @return
     */
    public int getLayoutHeight() {
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object obj = clazz.newInstance();
            Field field = clazz.getField("status_bar_height");
            int height = Integer.parseInt(field.get(obj).toString());
            return getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ;
    }
}
           

這裡需要注意的是,擷取我們自定義的狀态欄的高度設定參數的代碼,我們是放在view.post(new Runnable…)中的,為什麼要放在這裡面而不直接寫呢,如果直接在onCreate方法裡面擷取一個view的參數如寬高等,是擷取不到的,一直會是0,因為在onCreate方法中,也許view還沒執行測量方法。

那為什麼放在post方法中就能擷取到了呢?這裡是将Runnable添加到消息隊列中,保證在UI線程中執行,這裡就能保證在View繪制完成之後擷取到寬高,就能取到值了。

最終的執行效果如下:

實作沉浸式的三種方式

第三種方式:使用Toolbar自動帶有沉浸式的效果

Toolbar的具體使用方式詳見:http://blog.csdn.net/sinat_35159441/article/details/76794117

其實本質就是5.0自動實作了沉浸式的效果,通過主題的設定來改變狀态欄的顔色。colorPrimaryDark這個屬性就是用來顯示狀态欄的顔色的。

<style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
        <item name="android:textColor">@color/mytextcolor</item>
        <item name="colorPrimary">@color/colorPrimary_pink</item>
        <item name="colorPrimaryDark">@color/colorPrimary_pinkDark</item>
           

繼續閱讀