在Android 5.0之后引入了MD风格,从而状态栏沉浸也成为了一种设计习惯。而停留在之Android L之前的Android系统则不能直接实现沉浸式,这里就介绍一下如何实现Android K系列的伪沉浸式。
关于沉浸式效果,这里随便贴几张图吧
images/loading.gif' data-original="http://images2015.cnblogs.com/blog/732157/201607/732157-20160722110842654-592776228.png" />
Android L效果图
Android 4.2效果图
可以看出在Android K系列中,状态栏是渐变的效果
下面开始讲解如何实现上图的效果,在此就不赘述Android L或以上的沉浸式的效果实现了,在
题外话:这篇文章介绍的都是使用Android Studio作为IDE开发Android的,如果使用的是其他IDE应按照相关设置进行设置或者配置
开始学习伪沉浸式
所谓的其他知识,就是创建一个其他App中的Activity共有的基类BaseActivity,让其继承AppCompatActivity,然后在基类中实现伪沉浸式,这样Acticity就能专注于自己的内容,而把这些共有的设置交给BaseActivity处理。
现在看看这部分如何处理,先看代码:
1 public class BaseActivity extends AppCompatActivity { 2 3 private int mColor; 4 5 public BaseActivity(){ 6 } 7 8 public BaseActivity(int color){ 9 super();10 mColor = color;11 }12 13 @Override14 protected void onCreate(@Nullable Bundle savedInstanceState) {15 super.onCreate(savedInstanceState );16 StatusBarCompat.compat(this, ContextCompat.getColor(this, mColor));17 }18 19 public static class StatusBarCompat{20 21 private static final int INVALID_VAL = -1;22 private static final int COLOR_DEFAULT = Color.parseColor("#20000000");23 24 public static void compat(Activity activity, int statusColor){25 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){26 if(statusColor != INVALID_VAL){27 activity.getWindow().setStatusBarColor(statusColor);28 }29 return;30 }31 32 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT33 && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){34 int color = COLOR_DEFAULT;35 ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);36 37 if(statusColor != INVALID_VAL){38 color = statusColor;39 }40 41 View statusBarView = new View(activity);42 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,43 getStatusBarHeight(activity));44 statusBarView.setBackgroundColor(color);45 46 contentView.addView(statusBarView, lp);47 //contentView.addView(statusBarView, 0, lp);48 }49 }50 51 public static void compat(Activity activity){52 compat(activity, INVALID_VAL);53 }54 55 public static int getStatusBarHeight(Context context){56 int result = 0;57 58 int resourceId = context.getResources().getIdentifier("status_bar_height",59 "dimen", "android");60 61 if(resourceId > 0){62 result = context.getResources().getDimensionPixelSize(resourceId);63 }64 65 return result;66 }67 }68 }
跟着步骤,没必要全部看那些凌乱的代码,在这里讲解重点部分,在BaseActivity中提供了一个单一参数的构造函数,目的是让子类选择伪沉浸的颜色,在onCreate函数中调用了StatusBarCompat.compat(this, ContextCompat.getColor(this, mColor))函数,StatusBarCompat是其内部类,我们看看compat函数是如何实现伪沉浸的。
第一个if是判断系统如果为Android L或以上的系统则直接调用setStatusBarColor函数,这是API 21之后提供设置状态栏颜色的函数,然后是第二个if用于判断是否为Android K系统,如果是则开始我们的步骤。里面的内容其实是这样的,我们在
1 <?2 <resources>3 <style name="AppTheme" parent="@style/BaseAppTheme">4 <item name="android:windowTranslucentStatus">true</item>5 </style>6 </resources>
顺便看看BaseAppTheme的代码,这部分代码在res/values/styles里面:
1 <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">2 <!-- Customize your theme here. -->3 <item name="colorPrimary">@color/colorPrimary</item>4 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>5 <item name="colorAccent">@color/colorAccent</item>6 </style>
其中android:windowTranslucentStatus属性设置的是状态栏是否设置为透明状态,这个是v19之后才引入的属性。
到这里,看似好像完成了,但问题还没完全解决,那就是ToolBar的空间位置问题,假如不处理,如图:
看出效果是ToolBar和状态栏挤成了一块,但这不是这篇文章中所想要的效果,那应该怎么办呢?其实只需设置ToolBar的一个属性android:fitsSystemWindows="true"即可。该属性的意义就是让当前设置这个属性的view设置对应的padding为状态栏腾出对应的空间,说白了就好像是paddingTop=statusHeight。
按步骤设置好之后,还有一步,不然看到的是代码里面默认设置的颜色,所以要在Activity中传递color给BaseActivity,简单的代码如下:
1 public MainActivity(){2 this(R.color.colorPrimary);3 }4 5 private MainActivity(int color){6 super(color);7 }
只需修改R.color.colorPrimary为自己需要的颜色即可。为什么需要这样操作,很简单,因为默认启动调用的是无参构造函数,所以让无参去调用有参构造,即可实现,这也解释了为什么父类要去定义这个有参构造了。
运行了一下效果,嗯,还不错,但当你如果用的是这个方法添加的view作状态栏背景色的话,其实有一个坑,不过我贴的代码上已经解释了这个坑的处理方法了。这个坑其实就是和DrawerLayout配合使用的时候,当你打开抽屉的时候,会看到侧滑菜单在状态栏的下面,如图所示:
可以看到,状态栏把侧滑菜单挡住了,说白了其实是我们添加的view把状态栏挡住了。如何解决呢,在上面代码中注释了一句,其实使用下面那个三参数的函数就可以解决这个问题了,如图:
可以看出,侧滑菜单已经覆盖在充当状态栏背景的那个view上面了。为什么会这样呢,理由很简单,使用第一个函数的时候它是直接add到FrameLayout最上面的,所以就挡在了我们的布局上面,而addView(statusBar, 0, lp)的意思则是插入到第1个View的位置,因此就会让它插入到我们的布局下面,因此就实现了我们所想要的效果。既然两个参数有先后问题,那我们是否可以在Activity的onCreat函数中这样操作呢,比如先super.onCreat然后再调用setContentView,看似这样子我们的布局就应该在充当状态栏背景的view上面了,其实这是一个坑,我们在onCreat中必须是先调用setContentView然后再调用基类的onCreat,否则,状态栏的效果如图:
其实,从setContentView的名字可以看出来为什么了,既然这个是设置自定义布局,显然,调用这个函数的时候会将FrameLayout里面的内容清空,因此后调用这个函数的时候,之前add
进去的view已经被清空了。
到这里,关于Android K的伪沉浸式效果就实现了。
原标题:实现Android K的伪沉浸式
关键词:Android