状态栏适配

由于不同版本的系统的原因,很多时候我们需要对状态栏做不同的支持方案,主要是针对4.4,5.0以及6.0三种版本的系统。这里统一的使用的一种适配方案,避免自己写复杂的判断逻辑。主要原理如下:

  • 将Activity设置为全屏模式,使Activity能渗透到状态栏下,可以通过xml或者代码设置

  • 将状态栏设置为透明色

  • 自定义标题栏(可使用ToolBar,但考虑到项目里的标题栏完全不符合Android规范,因此使用的是完全自定义的标题栏),在标题栏上方多增加一块区域,刚好和状态栏大小一致

  • 设置标题栏的额外区域的颜色,以达到另辟蹊径地改变状态栏地颜色

  • 最后是需要解决一个manifest中的windowSoftInputMode属性在全屏模式下的bug

下面我们跟着这个思路一步步看如何去做状态栏适配:

  1. 在manifest中的application节点里,设置theme属性为corelibs的AppBaseCompactTheme

     <application
         android:name=".App"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:supportsRtl="true"
         android:theme="@style/AppBaseCompactTheme">
  2. 在BaseActivity的OnCreate里增加全屏以及透明状态栏的代码(默认已设置好,无需额外代码):

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         ...
         setTranslucentStatusBar();
         ...
     }
  3. 自定义一个标题栏(NavBar),继承自com.corelibs.views.navigation.TranslucentNavBar。然后覆写三个构造函数(注意,两个参数的一定要覆写)以及两个抽象函数getLayoutId和initView。这里可以直接使用ButterKnife的注解。接着就可以调用一系列设置颜色以及背景图片的方法来达到适配状态栏的效果。示例:

    public class NavBar extends TranslucentNavBar {
    
     @Bind(R.id.test) TextView test;
    
     public NavBar(Context context) {
         super(context);
     }
    
     public NavBar(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
    
     public NavBar(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
    
     @Override
     protected int getLayoutId() {
         return R.layout.v_nav;
     }
    
     @Override
     protected void initView() {
         setImageBackground(R.mipmap.bg);
     }
    }
  4. 将NavBar放到布局文件里即可,注意根节点不能使用fitSystemWindows=“true”。

  5. 如果Activity或者Fragment中有使用EditText,并且windowSoftInputMode是adjustResize的情况下,软键盘弹出不会Resize布局。要解决这个问题需要在Activity或者Fragment添加一行代码即可:

    AndroidBug5497Workaround.assistActivity(activity);

扩展

  • TranslucentNavBar具体有哪些方法可以在源码里看到,都有注释,这里就不赘述了。

  • setTranslucentStatusBar会判断当前系统版本,将Activity设置为全屏,并将状态栏设置为透明

  • 如果需要使用大图作为背景,并且希望图片渗透到状态栏下,可以调用TranslucentNavBar的setTransparentColor()来将标题栏也设置为透明,然后使用布局将标题栏覆盖到大图背景上即可。

  • AndroidBug5497Workaround

当初遇到软键盘弹起布局不Resize的问题的时候,也是Google了很久才在StackOverFlow找到答案(具体链接忘记了)。AndroidBug5497Workaround这个类的思路就是基于那篇文章 - 利用为Activity的content view设置 OnGlobalLayoutListener来监听布局的变化。通过判断何时弹起了软键盘来手动设置content view的高度,以此模拟adjustResize的效果。

在此基础上,我加入了一些基于现状的扩展。比如键盘弹起后手动设置的高度要计算状态栏的高度,低于4.4的版本的系统不计算状态栏,不全屏的Activity也不计算。又比如某些机型会有底栏,这个底栏的高度要考虑在内,比如谷歌原生的系统,以及典型的华为系统。其中华为系统的底栏高度计算方式又因为系统版本各有不同(很坑!)。因此在适配上花了不少时间。有兴趣的可以看看源码(不好意思,没有注释)。

Last updated