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" 设置内容的顶部内边距-->
完成