Android高级-Material Design交互设计-沉浸式和CardView的分析和兼容原理

Android的沉浸式是从Android4.4开始的

有三种方式可以设置沉浸式:一种是设置Style,一种是代码的方式,还有一种是布局里添加占位状态栏

Style

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

代码:

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

接着我们看一下Android5.0以上是如何处理的,5.0以上是可以设置状态局域栏的颜色的,还是两种方式

   private void immersive(int mColor){
        //系统兼容处理
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
            return;
        }

        //系统版本>5.0才进行状态栏的颜色处理
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            Window window = getWindow();
            //清除透明状态栏的标识
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //添加一个绘制状态栏的标识
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏颜色透明
            window.setStatusBarColor(mColor);
            //窗口属性进行处理
            int visibility = window.getDecorView().getSystemUiVisibility();
            //布局内容全屏展示  View的常量
            visibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            //隐藏虚拟导航栏
            visibility |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            //防止内容区域大小发生变化
            visibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;

            window.getDecorView().setSystemUiVisibility(visibility);
        }else {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }

    }

效果:

通过Style设置:

   <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
     <item name="android:statusBarColor">@android:color/transparent</item>
       <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>

运行效果:就是上面有一层阴影

这种的需要再添加一个values-v21文件夹:之后再运行就可以去掉半透明遮罩

如下图所示

状态栏文字颜色修改

    private ViewGroup mDecorView;
    private Window mWindow;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_set_color);
        Button btn1 =(Button)findViewById(R.id.btn1);
        Button btn2 =(Button)findViewById(R.id.btn2);
        Button btn3 =(Button)findViewById(R.id.btn3);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        btn3.setOnClickListener(this);
        mWindow = getWindow();
        mDecorView = (ViewGroup) mWindow.getDecorView();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn1:
                immersive(Color.BLUE);
                setCommonUI(SetColorActivity.this,true);
                break;
            case R.id.btn2:
                immersive(Color.RED);
                break;
            case R.id.btn3:
                immersive(Color.BLACK);
                setCommonUI(SetColorActivity.this,false);
                break;
        }
    }

      private void immersive(int mColor){
        //系统兼容处理
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
            return;
        }
        //系统版本>5.0才进行状态栏的颜色处理
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            Window window = getWindow();
            //清除透明状态栏的标识
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //添加一个绘制状态栏的标识
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏颜色透明
            window.setStatusBarColor(mColor);
            //
            int visibility = window.getDecorView().getSystemUiVisibility();
                //布局内容全屏展示  View的常量窗口属性进行处理
            //visibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            //隐藏虚拟导航栏
            visibility |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            //防止内容区域大小发生变化
            visibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            window.getDecorView().setSystemUiVisibility(visibility);

        }else {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }

    }


     public static void setCommonUI(Activity activity, boolean setDarkFont) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (setDarkFont) {
                activity.getWindow().getDecorView().setSystemUiVisibility(
                                 View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            }else {
                activity. getWindow().getDecorView().setSystemUiVisibility(
                                 View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            }
        }
    }
    }

运行效果:可以随意改变状态栏颜色和状态栏字体颜色,状态栏字体颜色就是黑色和白色两种;但是这只是谷歌支持的,

miui和魅族的字体颜色和状态栏颜色需要单独设置

 

 出现这个效果我们先来看一下WindowManager 相关特性详解:

 

1,WindowMananger.FLAG_TRANSLUCENT_STATUS: (>=api16)//

  • 半透明StatusBar,并且不会因用户交互而被清除。
  • 设置了此flag,系统会自动设置View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

2,WindowMananger.FLAG_FULLSCREEN

  1. 用于隐藏StatusBar
  2. 使用此flag,系统会自动忽略输入法的SOFT_INPUT_ADJUST_RESIZE的特性。

3,WindowMananger.FLAG_TRANSLUCENT_NAVIGATION

1.半透明NavigationBar,并且不会因用户交互而被清除。
2.设置了此flag,系统会自动设置View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
最低版本支持:Android4.4 (api 19)

4,WindowMananger.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS

1.用于未StatusBar和NavigationBar设置背景颜色。
2.原理:将StatusBar和NavigationBar设置为透明背景,并且将StatusBar和NavigationBar所在空间设置为Window.getStatusBarColor()Window.getNavigationBarColor()方法获得的颜色。
最低版本支持:Android5.0 (api 21)

 

第三种:占位状态栏


    public static void setStatusBar(Activity activity,int mColor){
        //拦截 判断decorview是否添加了statusbarview
        ViewGroup decorView =(ViewGroup) activity.getWindow().getDecorView();
        int count = decorView .getChildCount();
        if (count >0 && decorView.getChildAt(count -1) instanceof StatusBarView){
            //如果已经有这个顶部view了  就直接修改颜色就可以了
            decorView.getChildAt(count - 1).setBackgroundColor(mColor);
            return;
        }
        //原因:decorView是framelayout布局
        StatusBarView statusBarView =new StatusBarView(activity);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(mColor);
        decorView.addView(statusBarView);
    }
public class StatusBarView extends View{
    public StatusBarView(Context context) {
        super(context);
    }

    public StatusBarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public StatusBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

 附上一张图, 

运行结果:从结果可以看到,我们设置完占位图以后,再点击上面的button,状态栏并不会变色了,因为占位图是在Decorview(也就是framLayout)的上层,上层挡住了下面view的变化

 

 

但是项目开发过程中可能会有toolbar,也就是标题栏,我们来添加一下

运行效果“,沉浸式被标题栏挡住了

我们需要将toolbar进行下移操作,下移的高度就是状态栏的高度

  public int getStatusBarHeight(Context context){
        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0){
            return context.getResources().getDimensionPixelSize(resId);
        }
        return 0;
    }
    public void setHeightAndPadding(Context context, View view){
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        layoutParams.height += getStatusBarHeight(context);
        view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + getStatusBarHeight(context), view.getPaddingRight(), view.getPaddingBottom());
    }

这个时候我们把toolbar增加了一个状态栏的高度,显示效果如下

 

compile 'com.gyf.barlibrary:barlibrary:2.3.0'

后面再详细解析----

沉浸式我的项目中用的是

ImmersionBar

地址: https://gitee.com/liumifeng222/ImmersionBar

// 基础依赖包,必须要依赖
implementation 'com.gyf.immersionbar:immersionbar:3.0.0-beta03'
// fragment快速实现(可选)
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0-beta03'
// kotlin扩展(可选)
implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0-beta03'

这个可以适用于Activity、Fragment、DialogFragment、Dialog,并且适配刘海屏,适配软键盘弹出等问题

使用很方便。

接着学习CardView

添加依赖

implementation 'com.android.support:cardview-v7:28.0.0'

在布局中添加:

  <android.support.v7.widget.CardView android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="20dp"
        app:cardBackgroundColor="@color/colorPrimary"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="true"
        app:cardCornerRadius="8dp"
        app:contentPadding="10dp"
        android:clickable="true"
        android:foreground="?attr/selectableItemBackground"
        app:cardElevation="10dp">

        <TextView android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="cardView"
            android:background="#ffff00"
            android:gravity="center"/>

    </android.support.v7.widget.CardView>
查看它的API:

<!--app:cardBackgroundColor="@color/colorPrimary"  设置cardView背景色 -->
<!--app:cardPreventCornerOverlap="false" 取消Lollipop以下版本的padding -->
<!--app:cardUseCompatPadding="true" 为 Lollipop 及其以上版本增加一个阴影padding内边距-->
<!--app:cardCornerRadius="8dp" 设置cardView圆角效果-->
<!--app:cardElevation="10dp" 设置cardView Z轴阴影大小-->
<!--app:cardMaxElevation="6dp" 设置cardView Z轴最大阴影-->
<!--app:contentPadding="10dp" 设置内容的内边距-->
<!--app:contentPaddingBottom="12dp" 设置内容的底部内边距-->
<!--app:contentPaddingLeft="12dp" 设置内容的左边内边距-->
<!--app:contentPaddingRight="12dp" 设置内容的右边内边距-->
<!--app:contentPaddingTop="12dp" 设置内容的顶部内边距-->

完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值