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_STABLE和View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2,WindowMananger.FLAG_FULLSCREEN:
- 用於隱藏StatusBar
- 使用此flag,系統會自動忽略輸入法的SOFT_INPUT_ADJUST_RESIZE的特性。
3,WindowMananger.FLAG_TRANSLUCENT_NAVIGATION
1.半透明NavigationBar,並且不會因用戶交互而被清除。
2.設置了此flag,系統會自動設置View.SYSTEM_UI_FLAG_LAYOUT_STABLE和View.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" 設置內容的頂部內邊距-->
完成