Android沉浸式状态栏的实现在4.4及以上的系统中

        Android4.4之后谷歌提供了沉浸式全屏体验,在沉浸式全屏模式下,状态栏、虚拟按键动态隐藏,应用可以使用完整的屏幕空间,按照Google的说法,给用户一种身临其境的体验。

        最近几个项目中都有实现沉浸式状态栏的需求,其实就是状态栏和标题栏色调保持一直。难点还是Android的版本适配问题。主要时4.4系统和5.0+的系统兼容性。4.4以下的就不要想了不支持状态栏颜色修改。

       

  • 先上干货,再来慢慢讲解(注意:WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS这个标记在4.4以上都是生效的,但是发现在5.0以上一些手机呈现背景色为半透明的黑色,并非全透明,所以在5.0及以上的系统还是用如下的方法是吧。)

系统版本在4.4及以上5.0以下的:
------------
//4.4到5.0
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
    //透明状态栏
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //透明导航栏
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
系统版本在5.0及以上的:
------------
//5.0版本及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 
            | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
    getWindow().setNavigationBarColor(Color.BLACK);
}
 
  • 首先看下5.0及以上机型默认情况下的界面:默认下状态栏取styles.xml下的colorPrimaryDark值这里为红色;标题栏取colorPrimary值这里为蓝色;activity的背景色为白色。

       
  • 设置5.0及以上的代码后在5.0以上的机型上显示如下图:为了便于区分将背景设为粉色,此时发现activity的内容填充满整个屏幕。当通过setSystemUiVisibility(int visibility)方法设置:
    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN属性时表示:Activity全屏显示,但是状态栏不会被覆盖掉,而是正常显示,只是Activity顶端布局会被覆盖住;View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:隐藏导航栏;
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE:这个标记来帮助你的应用维持一个稳定的布局(这句话真他妈不能理解)。

    然后设置状态栏透明就能实现如下图的效果,不然状态栏会在上面盖住图中的hello world。通过setStatusBarColor(Color.TRANSPARENT)设置透明(这个方法只有在使用了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 并且没有使用 FLAG_TRANSLUCENT_STATUS的时候才有效。)。
    但是像下图的效果就很尴尬activity的内容填充到状态栏了,这个时候需要在布局文件里加入android:fitsSystemWindows="true":如果为true,将调整系统窗口布局以适应你自定义的布局,也就是调整了留出来系统的状态栏空间。最终效果如下图2。
    当然状态栏可以不设置透明而是根据需求设置相应的颜色,标题栏也同样,整体效果达成沉浸式就ok(当然我这标题栏蓝色就不是了,修改后的效果如图3)。
        
  • 另外附上setSystemUiVisibility(int visibility)的其他属性说明:
    
  1. SYSTEM_UI_FLAG_VISIBLE——显示状态栏和导航栏
  2. SYSTEM_UI_FLAG_LOW_PROFILE——此模式下,状态栏的图标可能是暗的
  3. SYSTEM_UI_FLAG_HIDE_NAVIGATION——隐藏导航栏
  4. SYSTEM_UI_FLAG_FULLSCREEN——全屏,隐藏状态栏和导航栏
  5. SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN——全屏,隐藏导航栏,状态栏浮在布局上。
  6. SYSTEM_UI_FLAG_IMMERSIVE——沉浸式:半透明的状态栏和导航栏
  7. SYSTEM_UI_FLAG_IMMERSIVE_STICKY——粘性沉浸式
  8. INVISIBLE —— Activity全屏显示,隐藏状态栏 


  • 4.4-5.0的机型上默认情况如下图:状态栏默认为黑色,并且只提供了translucent system bars(半透明系统栏,即顶部状态栏和底部导航栏)
 
  • 添加4.4-5.0的代码后在4.4的机型上显示如下图:状态栏半透明了(布局里任然需要设置android:fitsSystemWindows="true",这里为了展示将activity的背景设为绿色了)。4.4上面想要修改状态栏的颜色就稍微要麻烦一点了,因为没有提供5.0以上的直接换状态栏颜色的方法。那么办了?有一种偷懒的方法:将activity的背景设置为状态栏需要的颜色,然后在acitivity的跟布局下面(也就是标题栏下的内容设置成其他需要的颜色)但是这存在局限性就是每个activity都需要单独设置内容布局颜色。    那还有其他什么办法?  这就需要我们自己生成一个和状态栏大小相同的半透明矩形条,让他代替系统状态栏。
    

  • 具体代码见下:
    	        调用setStatusBarColor(Activity activity,int color)就可以设置状态栏的颜色,实现原理和过程自行百度了解。(注意代码中绘制和状态栏高度相同的矩形view时动态设置了它的id,这个id写在了ids.xml里了,findVewById的时候可以通过R.id.statusbarutil_fake_status_bar_view调用)
    
//设置4.4系统状态栏的颜色方法
private static void setStatusBarColor(Activity activity,int color){
    ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
    View fakeStatusBarView = decorView.findViewById(R.id.statusbarutil_fake_status_bar_view);
    if (fakeStatusBarView != null) {
        if (fakeStatusBarView.getVisibility() == View.GONE) {
            fakeStatusBarView.setVisibility(View.VISIBLE);
        }
        fakeStatusBarView.setBackgroundColor(color);
    } else {
        decorView.addView(createStatusBarView(activity,color));
    }
    setRootView(activity);
}
// 绘制一个和状态栏一样高的矩形
private static View createStatusBarView(Activity activity,int color) {
    View statusBarView = new View(activity);
    LinearLayout.LayoutParams params =
            new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
    statusBarView.setLayoutParams(params);
    statusBarView.setBackgroundColor(color);
    //动态设置view的id
statusBarView.setId(R.id.statusbarutil_fake_status_bar_view); return statusBarView;}// 获得状态栏高度private static int getStatusBarHeight(Context context) { int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId);}//设置根布局参数private static void setRootView(Activity activity) { ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); for (int i = 0, count = parent.getChildCount(); i < count; i++) { View childView = parent.getChildAt(i); if (childView instanceof ViewGroup) { childView.setFitsSystemWindows(true); ((ViewGroup) childView).setClipToPadding(true); } }}
  • 调用setStatusBarColor(Activity activity,int color)后的效果图如下:文中的标题栏可以通过设置主题NoActionBa取消掉添加自己的标题栏。
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一生之约

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值