首先说一下我对沉浸式状态栏的理解,在4.4之前,状态栏都是黑乎乎的,看起来很不美观,在4.4之后可以将状态栏设置成透明并和标题栏同一种颜色。以下是我总结的实现沉浸式的几种方式。
第一种方式:使用系统API实现沉浸式
1.1、首先看布局文件
添加android:fitsSystemWindows=”true”, android:clipToPadding=”true”两个属性
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="teststatusbar.com.xn.teststatusbar.MainActivity">
<TextView
android:background="@android:color/holo_blue_dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:fitsSystemWindows="true"
android:onClick="firstWay"
android:text="第一种方式实现沉浸式状态栏" />
</LinearLayout>
或者直接设置属性:
<item name="android:statusBarColor">@color/system_bottom_nav_color</item>,
这个属性是直接设置状态栏的颜色,这个属性是在style中设置的。或者直接用代码来改变颜色,只在5.0及以上才能起作用。
//5.0+可以直接用API来修改状态栏的颜色。 getWindow().setStatusBarColor(getResources().getColor(R.color.material_blue_grey_800));
<item name="android:windowTranslucentStatus">true</item>
这个属性就是设置状态栏为透明,同样在style文件中来设置的,但是有个弊端就是状态栏会往上移,所以标题栏的高度会减少,减少的高度为状态栏的高度,大概是24dp。这时我们通过反射机制来动态增加高度,或者给Toolbar设置android:fitsSystemWindows=”true”,或者给最外层的容器设置这个属性,这样也可以将减少的高度补回来。
1.2、java代码如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initStatusbar();
}
/**
* 初始化状态栏
*/
private void initStatusbar() {
//这里是判断当前的目标版本是否在4.4及以上,如果在4.4之上我们才设置沉浸式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//透明导航栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
}
效果如下:
第二种方式:使用反射机制动态加载标题栏
思路是这样的:先获取到状态栏的高度,再获取到我们自定义的标题栏的高度,然后将我们的标题栏的高度设置为两者之和,在这之前需要将我们原本的状态栏设为透明。这样就完成了我们的沉浸式状态栏。
2.1:在布局文件中定义好自定义的标题栏
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="teststatusbar.com.xn.teststatusbar.SecondActivity">
<LinearLayout
android:id="@+id/line"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@android:color/holo_blue_dark">
<TextView
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第二种方式实现沉浸式状态栏" />
</LinearLayout>
</LinearLayout>
高度我们设置的80dp。
2.2、在java代码中动态设置状态栏的高度
public class SecondActivity extends AppCompatActivity {
LinearLayout lin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
lin = (LinearLayout) findViewById(R.id.line);
setStatus();
}
/**
* 设置沉浸式状态栏
*/
private void setStatus() {
//判断是否是大于当前版本4.4,如果大于则实现沉浸式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//标题栏透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//导航栏透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
lin.post(new Runnable() {
@Override
public void run() {
final int statusheight = getLayoutHeight();
final int linHeight = lin.getHeight();
Log.e("statusheight linHeight", ""+statusheight+":"+linHeight);
ViewGroup.LayoutParams layoutParams = lin.getLayoutParams();
layoutParams.height = statusheight + linHeight;
lin.setLayoutParams(layoutParams);
}
});
}
}
/**
* 获取状态栏的高度
*
* @return
*/
public int getLayoutHeight() {
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object obj = clazz.newInstance();
Field field = clazz.getField("status_bar_height");
int height = Integer.parseInt(field.get(obj).toString());
return getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
这里需要注意的是,获取我们自定义的状态栏的高度设置参数的代码,我们是放在view.post(new Runnable…)中的,为什么要放在这里面而不直接写呢,如果直接在onCreate方法里面获取一个view的参数如宽高等,是获取不到的,一直会是0,因为在onCreate方法中,也许view还没执行测量方法。
那为什么放在post方法中就能获取到了呢?这里是将Runnable添加到消息队列中,保证在UI线程中执行,这里就能保证在View绘制完成之后获取到宽高,就能取到值了。
最终的执行效果如下:
第三种方式:使用Toolbar自动带有沉浸式的效果
Toolbar的具体使用方式详见:
其实本质就是5.0自动实现了沉浸式的效果,通过主题的设置来改变状态栏的颜色。colorPrimaryDark这个属性就是用来显示状态栏的颜色的。
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:textColor">@color/mytextcolor</item>
<item name="colorPrimary">@color/colorPrimary_pink</item>
<item name="colorPrimaryDark">@color/colorPrimary_pinkDark</item>