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" 設置內容的頂部內邊距-->

完成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章