作为Android开发,在解决4.4沉浸式状态栏遇到挺多问题的,这里列出我自己的解决方案,仅供参考。
首先是主题的配置:
默认主题 styles配置:
<style name="AppTheme" parent="android:Theme.Light">
<item name="windowNoTitle">true</item>
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
v19以及以上版本主题 styles配置:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
这里属性windowTranslucentStatus和windowTranslucentNavigation很重要,不然自定义的沉浸式状态栏无效。
然后就是布局文件中的属性:
android:fitsSystemWindows="true"
该属性如果不设置的话,那么就需要完全自定义StatusBar和NavigationBar。
这里我的解决方案是自定义一个BaseActivity类。里边预设一个沉浸式菜单样式。列出部分代码。
初始化一个系统状态栏。
/**
* @param color 顶部状态栏颜色
* @param alpha 顶部状态栏透明度
*/
public void initSystemBar(int color, float alpha) {
if (mTintManager == null) {
mTintManager = new SystemBarTintManager(this);
setTranslucentStatus(true);
try {
Field field = mTintManager.getClass().getDeclaredField("mNavBarAvailable");
field.setAccessible(true);
Object obj = field.get(mTintManager);
mNavBarAvailable = obj instanceof Boolean ? (Boolean) obj : false;
Field field1 = mTintManager.getClass().getDeclaredField("mNavBarTintView");
field1.setAccessible(true);
Object view = field1.get(mTintManager);
mNavBarTintView = view instanceof View ? (View) view : null;
if(mNavBarTintView!=null){
mNavBarTintView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if(navBarLayoutChangeListener!=null)
navBarLayoutChangeListener.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
mTintManager.setStatusBarTintEnabled(true);
mTintManager.setNavigationBarTintEnabled(true);
mTintManager.setStatusBarAlpha(alpha);
mTintManager.setStatusBarTintColor(getResources().getColor(color));
mTintManager.setNavigationBarAlpha(mNavBarAvailable && navVisiablity == View.VISIBLE ? 1.0f : 0.0f);
mTintManager.setNavigationBarTintColor(getResources().getColor(R.color.colorPrimaryDark));//底部状态栏默认颜色
}
顺便列出对于部分手机底部状态栏可隐藏解决方法。如果有比较好的方法可以告诉我。我这里主要是写一个死循环定期去检测底部状态栏(应该不是很好),所以做了一定的处理,获取底部状态栏是否可用,如果不可用就不启动死循环检测。虽然网上有很多方法说去检测状态栏可见性,但是好像没什么效果。
在onResume方法启动检测。
@Override
protected void onResume() {
super.onResume();
initSystemBar(R.color.colorPrimaryDark);
startNavBarTask();
}
在onPause方法暂停检测。
@Override
protected void onPause() {
super.onPause();
onPauseNaBarTask();
}
在onDestroy方法停止检测。
@Override
protected void onDestroy() {
super.onDestroy();
cancelNaBarTask();
}
对于自定义顶部状态栏,我们只需要根据Android手机版本确定是否展示即可:
//根据版本确定是否显示StatusBar状态栏 系统版本大于等于19才显示
statusBar.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? View.VISIBLE : View.GONE);
对于自定义底部状态栏添加监听:(该方法是在BaseActivity中定义的,就是刚刚那个检测任务回调,当底部状态栏改变时)
//添加NavigationBar可见性监听
addNavBarVisiableChangeListener(new NavBarVisiableChangeListener() {
@Override
public void onNavBarVisiableChange(View navBarView, int visibility) {
if (navigationBar != null) {
navigationBar.setVisibility(visibility == View.VISIBLE ? View.VISIBLE : View.GONE);
}
}
});
当然这里还做了自定义底部状态栏高度检测,主要是有些手机状态栏高度不同,必须要做(网上有很多方法,但是都不太靠谱,这里我通过监听底部状态视图布局变化来实现的)
//设置NavigationBar布局监听,这里主要是因为系统的状态栏不同手机高度不同,所以要监听
setNavBarLayoutChangeListener(new NavBarLayoutChangeListener() {
@Override
public void onLayoutChange(View navBarView, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int navHeight = navBarView.getMeasuredHeight();
int height = navigationBar.getMeasuredHeight();
if (navHeight > 0 && navHeight != height) {
ViewGroup.LayoutParams lp = navigationBar.getLayoutParams();
if (lp != null)
lp.height = navHeight;
}
}
});
差不多核心代码都列出来,同时可以参考我自己做的一个demo。
github地址:https://github.com/ttarfall/StatusBarDemo.git