Android沉浸式設計(狀態列和導航欄)——封裝

鋸齒流沙發表於2017-12-26

上一篇文章《Android沉浸式設計》中我們學習了Android的沉浸式設計,那麼我們可不可以對上篇文章學習的內容做一個封裝呢,另外除了狀態列實現了沉浸式,有些手機是有虛擬導航欄的,比如華為系列的手機,那麼我們可以不可以也實現對底部導航欄的沉浸式設計呢?當然是可以的,本文就帶你實現沉浸式封裝(包括狀態列和底部導航欄)。

封裝最好是在BaseActivity裡面,這樣子每一個繼承BaseActivity的Activity都可以自動實現沉浸式。

這裡使用上一篇文章《Android沉浸式設計》用到的技術進行封裝: 狀態列:設定狀態列為透明狀態,通過反射獲取狀態列的高度,然後給toolbar設定PaddingTop。 導航欄:設定導航欄為透明狀態,需要預設一個高度為1或者0的view,然後獲取導航欄高度,把導航欄的高度設定為View的高度,給View設定背景即可。

1)BaseActivity


public class BaseTranslucentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //判斷版本,如果[4.4,5.0)就設定狀態列和導航欄為透明
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT
                && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //設定虛擬導航欄為透明
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }


    public void setOrChangeTranslucentColor(Toolbar toolbar, View bottomNavigationBar, int translucentPrimaryColor) {
        //判斷版本,如果[4.4,5.0)就設定狀態列和導航欄為透明
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT
                && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
            if (toolbar != null) {
                //1.先設定toolbar的高度
                ViewGroup.LayoutParams params = toolbar.getLayoutParams();
                int statusBarHeight = getStatusBarHeight(this);
                params.height += statusBarHeight;
                toolbar.setLayoutParams(params);
                //2.設定paddingTop,以達到狀態列不遮擋toolbar的內容。
                toolbar.setPadding(
                        toolbar.getPaddingLeft(),
                        toolbar.getPaddingTop() + getStatusBarHeight(this),
                        toolbar.getPaddingRight(),
                        toolbar.getPaddingBottom());
                //設定頂部的顏色
                toolbar.setBackgroundColor(translucentPrimaryColor);
            }
            if (bottomNavigationBar != null) {
                //解決低版本4.4+的虛擬導航欄的
                if (hasNavigationBarShow(getWindowManager())) {
                    ViewGroup.LayoutParams p = bottomNavigationBar.getLayoutParams();
                    p.height += getNavigationBarHeight(this);
                    bottomNavigationBar.setLayoutParams(p);
                    //設定底部導航欄的顏色
                    bottomNavigationBar.setBackgroundColor(translucentPrimaryColor);
                }
            }
        } else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            getWindow().setNavigationBarColor(translucentPrimaryColor);
            getWindow().setStatusBarColor(translucentPrimaryColor);
        } else {
            //<4.4的,不做處理
        }
    }

    /**
     * 獲取導航欄高度
     * @param context
     * @return
     */
    private int getNavigationBarHeight(Context context) {
        return getSystemComponentDimen(this, "navigation_bar_height");
    }

    /**
     * 獲取狀態列的高度
     *
     * @param context
     * @return
     */
    private int getStatusBarHeight(Context context) {
        // 反射手機執行的類:android.R.dimen.status_bar_height.
        return getSystemComponentDimen(this, "status_bar_height");
    }

    /**
     * 反射獲取高度
     * @param context
     * @param dimenName
     * @return
     */
    private static int getSystemComponentDimen(Context context, String dimenName) {
        // 反射手機執行的類:android.R.dimen.status_bar_height.
        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            String heightStr = clazz.getField(dimenName).get(object).toString();
            int height = Integer.parseInt(heightStr);
            //dp--->px
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }

    /**
     * 判斷是否顯示導航欄
     * @param wm
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    private static boolean hasNavigationBarShow(WindowManager wm) {
        Display display = wm.getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        //獲取整個螢幕的高度
        display.getRealMetrics(outMetrics);
        int heightPixels = outMetrics.heightPixels;
        int widthPixels = outMetrics.widthPixels;
        //獲取內容展示部分的高度
        outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        int heightPixels2 = outMetrics.heightPixels;
        int widthPixels2 = outMetrics.widthPixels;
        int w = widthPixels - widthPixels2;
        int h = heightPixels - heightPixels2;
        return w > 0 || h > 0;//豎屏和橫屏兩種情況。
    }

}
複製程式碼

BaseTranslucentActivity的所做的事情基本在上面已經分析了,如果還有不明白的可以檢視註釋。

2)activity需要繼承BaseActivity

public class TranslucentActivity06 extends BaseTranslucentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_translucent06);
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        setOrChangeTranslucentColor(toolbar,null,0xffffD306);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
                setOrChangeTranslucentColor(toolbar,null,0xffffD3ff);
            }
        });
    }

}
複製程式碼

這裡需要手動呼叫setOrChangeTranslucentColor方法設定沉浸式。

3)xml佈局

<?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"
    android:background="?attr/colorPrimary"
    android:orientation="vertical"
    tools:context="com.main.translucent.TranslucentActivity07">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
        app:title="@string/app_name"
        app:titleTextColor="#ff0"
        >
    </android.support.v7.widget.Toolbar>


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#fff">

        <android.support.v7.widget.LinearLayoutCompat
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:divider="@drawable/abc_list_divider_mtrl_alpha"
            app:showDividers="beginning|middle">

            <android.support.v7.widget.AppCompatButton
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="24dp"
                android:layout_marginTop="23dp"
                android:onClick="showDialog"
                android:text="對話方塊"/>

            <CheckBox
                android:id="@+id/checkBox1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="CheckBox"/>

            <RadioButton
                android:id="@+id/radioButton1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="RadioButton"/>
        </android.support.v7.widget.LinearLayoutCompat>
    </ScrollView>

    <View
        android:id="@+id/nav"
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:layout_weight="0"
        android:background="?attr/colorPrimary"
        />
</LinearLayout>
複製程式碼

注意:這裡底部預設了一個View給導航欄。如果不想改變導航欄的,可以不預設,呼叫setOrChangeTranslucentColor方法的時候,第二個引數直接傳null即可。

執行效果圖:

沉浸式設計

以上程式碼的BaseTranslucentActivity類就是實現沉浸式設計的封裝,哪裡不明白的或者你有更好的設計方案,歡迎致信,一起交流。

相關文章