Android UI——Material Design ——沉浸式设计

Android中的沉浸式设计

在Android官方的Material Design指导中,有一种界面的设计方案是沉浸式设计。所谓的沉浸式设计,就是只App的界面完全和屏幕和系统融合。而不是带有系统组件的特点。例如:标题栏一般都是有系统的颜色的,比如黑色状态栏 浅灰色状态栏 。导航栏也有系统的颜色。沉浸式就是通过修改一些组件的风格和效果。使得和当前运行的App一致,达到整个界面都是相同的设计元素。
沉浸式个人认为来说是一个设计的思想。但是对于实现的方案有不同的实现。各个大厂也都有自己的实现方案。这里我总结个人的沉浸式的实现方式。也是目前用在项目中的沉浸式设计方案

由于Android 有很多版本 各个版本的效果差异比较明显,所以在我们实现沉浸式的时候。要考虑兼容问题。针对不同版本有不同的实现方案。
官方的沉浸式Translucent:就是让整个App沉浸在屏幕里面,有点类似全屏的效果。

标题栏沉浸式设计

针对5.0以上的API

1 我们可以通过设置主题


        

2 可以通过设置样式属性来解决。可以设置style.xml

@color/system_bottom_nav_color

3 通过代码设置

getWindow().setStatusBarColor(getResources().getColor(R.color.material_blue_grey_800));
        (注意:要在setContentView方法之前设置)

针对4,4API

由于在4.4中新增了API,可以设置状态栏为透明的
1 可以在属性样式里面解决(这种方式不推荐,会出现兼容性的问题)

true

2 可以在代码里解决

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_main);

在这种情况下,会出现APP的内容被顶到了上面,状态栏会遮挡界面
解决方式如下:
1 给ToolBar设置android:fitsSystemWindows=true
这个属性的作用是:在设置布局时,是否考虑当前系统窗口的布局,如果设置为true就会调整整个系统窗口布局包括状态栏的view以适应你的布局。
但是这种情况下,当里面有ScrollView并且里面有Edittext的时候,就会出现软键盘弹起后会把toolbar拉取下来的bug
2 这里我们推荐的做法是,在布局最外层容器设置android:fitsSystemWindows=true,可以达到状态栏不会被输入法影响产生Bug

步骤:

* 1.在最外层容器设置android:fitsSystemWindows="true"
* 2.不要给Toolbar设置android:fitsSystemWindows="true"
    * 2.直接将最外层容器(也可以修改-android:windowBackground颜色)设置成状态栏想要的颜色
    * 3.下面剩下的布局再包裹一层正常的背景颜色。

3 修改ToolBar的高度
1.不要给Toolbar设置android:fitsSystemWindows="true"
2.需要知道状态栏的高度是多少?去源码里面找找

                
                24dp
                
                48dp
                反射手机运行的类:android.R.dimen.status_bar_height.
3.修改Toolbar的PaddingTop(因为纯粹增加toolbar的高度会遮挡toobar里面的一些内容)
                toolbar.setPadding(
                    toolbar.getPaddingLeft(),
                    toolbar.getPaddingTop()+getStatusBarHeight(this), 
                    toolbar.getPaddingRight(),
                    toolbar.getPaddingBottom());

4.或者可以设置toolbar的高度(不推荐)

底部虚拟导航栏设计

5.x 调用提供的API实现

1 属性解决

navigationBarColor

2 代码

getWindow().setNavigationBarColor()

4.4版本 用一些特殊手段。设置底部虚拟导航栏为透明

步骤:
1)在布局底部添加一个高度为0.1dp的view
2)动态设置底部View的高度为虚拟导航栏的高度
View nav = findViewById(R.id.nav);
LayoutParams p = nav.getLayoutParams();
p.height += getNavigationBarHeight(this);
nav.setLayoutParams(p);

具体案例

我们需要创建一个BaseTranslucentActivity作为父Activity

/**
 * @author wxblack-mac
 * @DESCRIBE:沉浸式状态栏的父Activity
 * @DATE 2019/3/6 10:33
 * GOOD LUCK
 */
@SuppressLint("Registered")
public class BaseTranslucentActivity extends AppCompatActivity {

    private Toolbar toolbar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //判断系统版本
        //[4.4,5.0) 手动实现沉浸式状态栏和导航栏透明
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
                && Build.VERSION.SDK_INT < 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) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
                && Build.VERSION.SDK_INT < 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的,不做处理
        }
    }


    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");
    }

    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;
    }


    @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;
        System.out.println("~~~~~~~~~~~~~~~~h:" + h);
        return w > 0 || h > 0;//竖屏和横屏两种情况。
    }
}

在子Activity调用的时候 MainActivity

public class MainActivity extends BaseTranslucentActivity {

    private Toolbar toolbar;
    private View navigationView;

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = ((Toolbar) findViewById(R.id.toolbar));
        navigationView = findViewById(R.id.nav);
        setOrChangeTranslucentColor(toolbar, navigationView, getResources().getColor(R.color.colorPrimary));
    }
}

各个版本运行效果

Android UI——Material Design ——沉浸式设计_第1张图片
Android 4.4
Android UI——Material Design ——沉浸式设计_第2张图片
Android 5.0
Android UI——Material Design ——沉浸式设计_第3张图片
Android 6.0

你可能感兴趣的:(Android UI——Material Design ——沉浸式设计)