Android"沉浸式"体验

首先声明一下这个叫法应该是不对的,Translucent翻译过来的是半透明效果,不是IOS的那种什么沉浸式

1. 概念

首先要明确1个概念,在android上,“沉浸式”叫沉浸式全屏模式以及透明化系统状态栏其实这个也没啥好说的,不管你是android粉还是IOS粉,在日常玩机的过程中,都见过这种界面效果

《Android 这里写图片描述
《Android 这里写图片描述 注意图片中的红色部分,相对于传统app的黑色状态栏,这种类型app的布局是一直延伸到状态栏上

2.实现方式

强调一下,“沉浸式”仅仅支持在不低于android4.4的设备上运行,并不向下兼容。并且由于谷歌在android5.0上推出了Material Design,所以4.4跟5+实现方式并不完全一样

  • 第一种需求实现方式
    在android5.0以上,官方已经提供了透明化系统状态栏的功能支持,就是将colorPrimary与colorParimaryDark设置成一致就行了
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar"> 
    <!-- Customize your theme here. --> 
    <item name="colorPrimary">@color/colorPrimary</item> 
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 
    <item name="colorAccent">@color/colorAccent</item>
</style>

但是在android4.4上面,实现方式略有不同,它是在透明模式下使用fitsSystemWindows将contentview移至到状态栏的下方,最后在这个空出来的地方手动添加一层view覆盖上去,达到效果

if (Build.VERSION.SDK_INT==Build.VERSION_CODES.KITKAT) { 
    //将状态栏设置成全透明 
    int bits=WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 
    if ((params.flags & bits)==0) { 
        params.flags |= bits; 
        //如果是取消全透明,params.flags &= ~bits; 
        window.setAttributes(params); 
    } 
    //设置contentview为fitsSystemWindows 
    ViewGroup viewGroup= (ViewGroup) findViewById(android.R.id.content); 
    viewGroup.getChildAt(0).setFitsSystemWindows(true); 
    //给statusbar着色 
    View view=new View(this); 
    view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(this))); 
    view.setBackgroundColor(getResources().getColor(R.color.colorPrimary));     
    viewGroup.addView(view);
}
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { 
    //亲儿子里面遇到的问题,不加fitsSystemWindows直接变成全透明样式了
    //设置contentview为fitsSystemWindows
    ViewGroup viewGroup= (ViewGroup) findViewById(android.R.id.content);
    if (viewGroup.getChildAt(0)!=null) {    
        viewGroup.getChildAt(0).setFitsSystemWindows(true);
    }
    window.setStatusBarColor(getResources().getColor(R.color.colorPrimary));
}
public static int getStatusBarHeight(Context context) {   
    int result = 0;    
    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");    
    if (resourceId > 0) {        
        result = context.getResources().getDimensionPixelSize(resourceId);    
    }    
    return result;
}

这段代码应该很好理解

有个地方主义一下,这个color,直接设置在有一部分手机上有问题,比如亲儿子(NEXUS6 android6.0),在顶部有一个透明的遮罩盖在那边

《Android 有透明遮罩

这个问题我在github上看laobie的
StatusBarUtil时候发现有这么一个关键点

/** 
* 计算状态栏颜色 
* @param color color值 
* @param alpha alpha值 
* @return 最终的状态栏颜色 
*/
private static int calculateStatusColor(int color, int alpha) {    
    float a = 1 - alpha / 255f;    
    int red = color >> 16 & 0xff;    
    int green = color >> 8 & 0xff;    
    int blue = color & 0xff;    
    red = (int) (red * a + 0.5);    
    green = (int) (green * a + 0.5);    
    blue = (int) (blue * a + 0.5);    
    return 0xff << 24 | red << 16 | green << 8 | blue;
}

《Android 无透明遮罩

作者在介绍中说了,这个状态栏颜色默认加上一个112的透明度,也就是中间值,所以现在我们自己设置了透明度,系统就不会自动加上了

  • 第二种需求实现方式
    这把我们先说4.4上如何实现。其实刚才在实现第一种需求的过程中,已经做了状态栏全透明处理,只是不要移位加层并着色即可,这里不多说android5.0上是将decorview整体变成全屏模式,并且将状态栏设置成全透明即可
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { 
      window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 
      window.setStatusBarColor(Color.TRANSPARENT); 
      findViewById(R.id.toolbar).setBackgroundColor(Color.TRANSPARENT);
}

这样,你的app就已经基本上达到了“沉浸式”的要求,是不是很简单。

3.深坑

  1. 我个人开发中写IM的过程中,遇到一个场景:底部edittext要想被软键盘弹起,contentview必须加上fitSystemWindows才能正常。

  2. 发现一个很奇怪的现象,之前我们提及fitSystemWindows的时候,说到rootview会被移步到状态栏的下方
    但是今儿在使用design包里面的CoordinatorLayout或者CollapsingToolbarLayout的时候,发现如果给其中的子view也设置上fitSystemWindows,那么view又置顶去了。。。

<android.support.design.widget.CoordinatorLayout   xmlns:android="http://schemas.android.com/apk/res/android"    
        android:orientation="vertical" 
        android:layout_width="match_parent"    
        android:layout_height="match_parent"    
        android:fitsSystemWindows="true">    
        <ImageView        
            android:layout_width="match_parent"        
            android:layout_height="wrap_content"        
            android:src="@mipmap/liuyan"        
            android:fitsSystemWindows="true"        
            android:scaleType="centerCrop"/>    
        <TextView        
            android:layout_width="match_parent"        
            android:layout_height="wrap_content"        
            android:text="123123123"/>
</android.support.design.widget.CoordinatorLayout>

看看效果

《Android

  1. 又他妈发现一个坑。。。自从小米升到6.0之后,我就没有用亲儿子在那边折腾。闲着无聊,装app看看现在的效果,艹不对头了啊,变成全透明那种样式了,但是状态栏颜色确实是变了。。。怎么破,很简单,把4.4上fitSystemWindows(true)再来设置一遍即可
    原文作者:皮球二二
    原文地址: https://www.jianshu.com/p/5e437126c877
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞