通过主题设置状态栏
在API21(android 5.0)之后,设置状态栏透明效果为半透明,并且为了保证在API19(android 4.4)正常使用,所以需要3份不同的style文件。即values-v19(android 4.4之后使用),values-v21(android 5.0之后使用),自带的values(android4.4~android5.0之间使用)。
在res文件下新建文件夹values-v19,在此文件中添加新的styles.xml文件。在API19时开始有android:windowTranslucentStatus这个属性,表示是否设置状态栏为半透明状态。同时需要设置导航栏为透明,也就是android:windowTranclucentNavigation属性,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
在res文件下新建文件夹values-v21,在此文件中添加新的styles.xml文件。在API21(android5.0)之后设置状态栏透明为半透明效果,为了解决这个问题,我们使用一个新的属性android:stautsBarColor,此属性为设置状态栏颜色,我们将其设置为无颜色,即透明。在使用statusBarColor时,必须将windowTranslucentStatus属性的值设置为false,否则statusBarColor无效。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
最后在默认的values中的styles.xml中添加一个空的TranslucentTheme主题,用于API19(android 4.4)以前。代码如下:
<style name="TranslucentTheme" parent="AppTheme">
</style>
最后记得在AndroidManifest.xml文件的application节点下把theme属性的值修改为“Translucent”。在vivo x9,android版本为7.1.2真机下测试效果如图:

由图可见,使用此方法设置状态栏透明后,整个布局延伸到了状态栏的下面。但是在某些需求下,我们依旧需要保存状态的区域。解决方法如下:
fitsSystemWindow属性
通过代码设置fitsSystemWindow属性。代码如下(可直接复制粘贴使用):
/**
* 通过style设置状态栏透明后,布局会延伸到状态栏,为了保留状态栏原本的位置
* 通过设置fitsSystemWindow,在顶部预留出状态栏高度的padding。
* @param activity activity(在baseActivity中无效)
* @param value 是否设置fitsSystemWindow
*/
public static void setFitsSystemWindow(Activity activity,boolean value){
//拿到整个布局
ViewGroup contentFrameLayout = activity.findViewById(android.R.id.content);
View parentView = contentFrameLayout.getChildAt(0);
if (parentView != null && Build.VERSION.SDK_INT >= 14){
parentView.setFitsSystemWindows(value);
}
}
效果如图(vivo x9 android7.1.2真机测试):

在使用fitsSystemWindow后,如果需要设置状态栏和背景颜色不同,就需要在最外层布局设置状态栏的颜色后再在状态栏下方设置背景颜色,并且在使用此属性后,点击EditText弹出软件盘后,软件盘会将整个布局顶出屏幕之外。所以在使用此方法的时候,看需求使用,避免返工修改。
添加占位View
在最外层的根布局中添加一个View,将View的高度设置为状态栏的高度。这样布局虽然还是延伸到了状态栏,但是达到了目标效果。以下是获取状态栏高度的代码以及View的代码:
/**
* 将占位View高度设置为状态栏的高度
* @param context 上下文
* @param statusBarView 占位View
*/
public static void setStatusBarViewHeight(Context context, View statusBarView) {
//获取状态栏高度
int result = 0;
int resourceId = context.getResources()
.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
//设置View的高度
ViewGroup.LayoutParams layoutParams = statusBarView.getLayoutParams();
layoutParams.height = result;
}
}
<View
android:id="@+id/status_bar_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0f0">
</View>
以下是效果图(android 7.1.2 vivo X9 真机测试):

也可以不在布局中添加View,直接在代码中动态添加占位状态栏,以下是封装好的代码:
/**
* 代码添加状态栏占位View
* @param activity 当前activity
* @param color 状态栏颜色
*/
public static void addStatusBarViewWithColor(Activity activity,int color){
//获得根布局
ViewGroup contentView = activity.findViewById(android.R.id.content);
View statusBarView = new View(activity);
//设置view的高宽
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
);
statusBarView.setBackgroundColor(color);
contentView.addView(statusBarView,layoutParams);
}
/**
* 获取状态栏高度
* @param activity 当前acitivity
* @return 状态栏高度
*/
private static int getStatusBarHeight(Activity activity) {
//获取状态栏高度
int result = 0;
int resourceId = activity.getResources().getIdentifier(
"status_bar_height",
"dimen",
"android"
);
if (resourceId > 0) {
result = activity.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
真机测试效果图:

如果使用的是Relativelayout,在添加状态栏占位View后,Relativelayout布局的内容可能和占位View重合,所以将上一中方法进行修改,在最大的根布局添加一个状态栏高度的paddingTop,这样即使重合也是重合的paddingTop。修改后的代码如下:
/**
* 代码添加状态栏占位View
* (注:最好是在跟布局中添加一个状态栏高度的paddingTop,如果布局是RelativeLayout,根布局会和
* 占位View重合。)
* @param activity 当前activity
* @param color 状态栏颜色
*/
public static void addStatusBarViewWithColor(Activity activity,int color){
//contentView注意和下面的decorView区分开
ViewGroup contentView = activity.findViewById(android.R.id.content);
//添加paddingTop
contentView.setPadding(0,getStatusBarHeight(activity),0,0);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP){
//5.0以上直接设置状态栏颜色
activity.getWindow().setStatusBarColor(color);
}else {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View statusBarView = new View(activity);
//设置view的高宽
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
);
statusBarView.setBackgroundColor(color);
decorView.addView(statusBarView,layoutParams);
}
}
通过代码设置
因为在API 21之后才会有setStatusBarColor这个方法,所以做个判断,当API大于等于21时,使用setStatusBarColor这个方法。在API 19之上 API 21 之下使用设置状态和导航栏的方法实现。下面是已经封装好的通过代码设置沉浸式状态的方法。
/**
* 代码设置沉浸式状态栏
* @param activity 当前activity
*/
public static void setStatusBarTransparent(Activity activity){
//KITKAT API 19
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
//半透明状态栏和半透明导航栏
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
//LOLLIPOP API 21
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
Window window = activity.getWindow();
//返回当前窗口属性
WindowManager.LayoutParams attributes = window.getAttributes();
//a = a | b;
attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}else {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.flags |= flagTranslucentStatus | flagTranslucentNavigation;
window.setAttributes(attributes);
}
}
}
以上就是全部内容。
有问题欢迎私聊或者发送邮箱(964427082@qq.com)一起讨论