上一篇文章《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类就是实现沉浸式设计的封装,哪里不明白的或者你有更好的设计方案,欢迎致信,一起交流。