伴随着 Android 5.0 发布的 Material Design,让 Android 应用告别了以前的工程师审美,迎来了全新的界面,灵动的交互,也让越来越多的 App 开始遵从 material design 设计原则,不再是以前拿着iOS设计稿,做着Android开发。本文就其中的沉浸式状态栏这一特性,描述其兼容到4.4的实现,以及一些使用中的小细节。

前言

在4.4之前状态栏一直是黑色的,在4.4中带来了 windowTranslucentStatus 这一特性,因此可以实现给状态栏设置颜色,如下图所示,状态栏颜色不再是黑色,而是可以定制的颜色。

国内将状态栏变色叫做沉浸式状态栏,时间久了,叫的人多了,大家就不再深究,默认了这种叫法。

需要解决的问题

4.4及其以上都是可以实现沉浸式状态栏效果的,5.0及其以上可以直接在主题中设置颜色,或者调用 Window 类中的 setStatusBarColor(int color) 来实现,这两种方式在5.0上都比较简单,但是如何兼容到4.4呢?

图片背景的页面,怎样让状态栏透明或者半透明(效果如下)?

使用 DrawerLayout 时,主界面实现沉浸状态栏同时,怎样保证抽屉视图也能延伸到状态栏(如下图所示),且兼容到4.4?

以上就是本文要解决的问题,下面给出解决方案。

解决方案

1. 给状态栏设置颜色

思路是:

先设置状态栏透明属性;

给根布局加上一个和状态栏一样大小的矩形View(色块),添加到顶上;

然后设置根布局的 FitsSystemWindows 属性为 true,此时根布局会延伸到状态栏,处在状态栏位置的就是之前添加的色块,这样就给状态栏设置上颜色了。

代码如下:

/**

* 设置状态栏颜色

*

* @param activity 需要设置的activity

* @param color 状态栏颜色值

*/

public static void setColor(Activity activity, int color) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

// 设置状态栏透明

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// 生成一个状态栏大小的矩形

View statusView = createStatusView(activity, color);

// 添加 statusView 到布局中

ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();

decorView.addView(statusView);

// 设置根布局的参数

ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);

rootView.setFitsSystemWindows(true);

rootView.setClipToPadding(true);

}

}

复制代码

其中生成状态栏一样大小的矩形色块的代码如下:

/**

* 生成一个和状态栏大小相同的矩形条

*

* @param activity 需要设置的activity

* @param color 状态栏颜色值

* @return 状态栏矩形条

*/

private static View createStatusView(Activity activity, int color) {

// 获得状态栏高度

int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");

int statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);

// 绘制一个和状态栏一样高的矩形

View statusView = new View(activity);

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,

statusBarHeight);

statusView.setLayoutParams(params);

statusView.setBackgroundColor(color);

return statusView;

}

复制代码

在 setContentView() 之后调用 setColor(Activity activity, int color) 方法即可。

2. 图片作背景时,状态栏透明

这个实现比较简单,根布局背景设置为图片,然后添加状态栏透明 Flag, 然后设置根布局的 FitsSystemWindows 属性为 true 即可。代码如下:

/**

* 使状态栏透明

*

* 适用于图片作为背景的界面,此时需要图片填充到状态栏

*

* @param activity 需要设置的activity

*/

public static void setTranslucent(Activity activity) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

// 设置状态栏透明

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// 设置根布局的参数

ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);

rootView.setFitsSystemWindows(true);

rootView.setClipToPadding(true);

}

}

复制代码

同样的,在 setContentView() 之后调用 setTranslucent(Activity activity) 方法即可。

3. 使用 DrawerLayout 时的特殊处理

注意点:

使用 DrawerLayout 时,此时不能再对根布局,即 DrawerLayout 进行设置,而要针对 DrawerLayout 的内容布局进行设置,即抽屉之外的另一个布局。

如下是一个典型的 DrawerLayout 的布局,其内容布局即 FrameLayout,我们需要对 FrameLayout 进行仿状态栏色块的添加、FitsSystemWindows 属性的设置。

android:id="@+id/drawer_layout"

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/main"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

android:background="@color/colorPrimary"

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

android:id="@+id/navigation"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_gravity="start"

app:headerLayout="@layout/nav_header"

app:menu="@menu/activity_main_drawer"/>

复制代码

还有一个需要注意的设置抽屉布局(Drawer)的 FitsSystemWindows 属性为 false,即上面布局中的 NavigationView。

解决方案

/**

* 为DrawerLayout 布局设置状态栏变色

*

* @param activity 需要设置的activity

* @param drawerLayout DrawerLayout

* @param color 状态栏颜色值

*/

public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// 生成一个状态栏大小的矩形

View statusBarView = createStatusBarView(activity, color);

// 添加 statusBarView 到布局中

ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);

contentLayout.addView(statusBarView, 0);

// 内容布局不是 LinearLayout 时,设置padding top

if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {

contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);

}

// 设置属性

ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);

drawerLayout.setFitsSystemWindows(false);

contentLayout.setFitsSystemWindows(false);

contentLayout.setClipToPadding(true);

drawer.setFitsSystemWindows(false);

}

}

复制代码

需要注意的是,DrawerLayout 的布局只能包含两个直接子布局,一个是内容布局,一个是抽屉布局,结构如前面的示例布局所示,如果内容布局的根布局如果不是 LinearLayout 需要对其子布局设置padding top值,否则仿状态栏色块会被遮挡在最下面,布局内容延伸到状态栏,如下图所示:

(ps:就上图中的问题,目前的解决方案感觉并不是很好,如果你有更好的解决方案,请告诉我~)

/**

* 为 DrawerLayout 布局设置状态栏透明

*

* @param activity 需要设置的activity

* @param drawerLayout DrawerLayout

*/

public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

// 设置状态栏透明

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// 设置内容布局属性

ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);

contentLayout.setFitsSystemWindows(true);

contentLayout.setClipToPadding(true);

// 设置抽屉布局属性

ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);

vg.setFitsSystemWindows(false);

// 设置 DrawerLayout 属性

drawerLayout.setFitsSystemWindows(false);

}

}

复制代码

同样的,在 setContentView() 之后调用上述解决方案中的方法即可。

在项目中使用

以上代码我整理成了一个工具类,放在 github 上:StatusBarUtils.java 文件

在项目中推荐这样使用,在 BaseActivity 中重写 setContentView(int layoutResID) 方法,新建一个 setStatusBarColor()方法,全局设置状态栏颜色,因为一般 App 大部分界面状态栏都是主题色。

public class BaseActivity extends AppCompatActivity {

@Override

public void setContentView(int layoutResID) {

super.setContentView(layoutResID);

setStatusBarColor();

}

protected void setStatusBar() {

StatusBarUtils.setColor(this, getResources().getColor(R.color.colorPrimary));

}

}

复制代码

当子类 Activity 的状态栏需要特殊处理时,比如设置不同的颜色,或者设置图片为背景时,重写父类的 setStatusBarColor() 方法即可,例如:

public class ImageStatusBarActivity extends BaseActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_image_status_bar);

}

@Override

protected void setStatusBar() {

StatusBarUtils.setTranslucent(this);

}

复制代码

对 DrawerLayout 布局使用时,需要注意一点,因为方法是在 setContentView() 之后立即调用的,所以传进来的 DrawerLayout 要通过 findViewById() 传进来。如果传入在 setContentView() 之后通过 findViewById() 得到的 DrawerLayout, 则会造成空指针异常。

StatusBarUtils.setColorForDrawerLayout(this, (DrawerLayout) findViewById(R.id.drawer_layout), getResources()

.getColor(R.color.colorPrimary));

复制代码

源码和Demo下载

效果在前文中都有截图,就不多放了。

如文章中有疏漏的地方,请联系我或在评论里告知。

android沉浸式状态栏 图片背景,Android App 沉浸式状态栏解决方案相关推荐

  1. android沉浸式状态栏 图片背景,Android 补充 LayerDrawable 沉浸式状态栏

    小菜前些日子整理了两次小小的沉浸式状态栏的总结:Android 沉浸式状态栏的多种样式 和 Android 沉浸式状态栏以及伪沉浸式状态栏.今天小菜再稍稍补充一点,Java/Kotlin 代码中设置 ...

  2. android arcgis使用自定义图片背景底图(tif图片制作)

    简介 arcgis在安卓中专业级位置服务中发挥了很大的作用,当然主要目的不是为了像百度地图那样显示地图,它包含了很多很多百度地图等不具备的功能.一般使用它都是用的范围很大的shp文件做底图,但是也有只 ...

  3. android带视频和图片的轮播(banner)解决方案

    方案只包含一个视频和多张图片,如果又多个视频的,可以修改适配器中的的播放器为一个list,并且在滑动中做相应的释放操作 一:实现一个视频和多张图片的轮播banner,使用到第三方框架有 1.轮播的基础 ...

  4. android动态设置冷启动图片拉伸变形,Android冷启动时间优化

    冷启动时间是指当用户点击你的app那一刻到系统调用Activity.onCreate()之间的时间段.在这个时间段内,WindowManager会先加载app主题样式中的windowBackgroun ...

  5. android 4.4 获取图片主色调,Android Lollipop:使用Palette抽取图片主色调

    使用Palette抽取Bitmap主色调 关于Palette 一些Support库随着Android Lollipop的发布而诞生了,其中就有Palette.这个库可以让你很轻松地从一幅图中抽取特征颜 ...

  6. android 文字转化为图片格式,Android 文字生成图片

    一直在看别人写的文章,而自己却不敢执笔来写,一是怕写得不好,二是平时也不太有写文章的习惯,所以总感觉看别人写就好啦,但是最近工作遇到点问题,本以为很简单的,但是奈何解决起来还是比较麻烦的 把Andro ...

  7. android支持svg格式图片么,Android Studio2.0中使用SVG图片格式

    SVG格式, 适应屏幕, 图片较小, 还有很多优点 . 本文讲解如何使用SVG格式. SVG: Scalable Vector Graphics, 可缩放矢量图形. IRI: Internationa ...

  8. android 6.0获取图片地址,Android应用开发Android 保存图片到系统相册(三星6.0有效)...

    Android   保存图片到系统相册(三星6.0有效).今天要做一个保存图片到系统图库的功能,自身能力较浅,所以只能搜索了但发现网上的方法有几处bug,所以自己总结一下防止以后忘掉也想和大家分享一下 ...

  9. android代码拿到图片路径,android图片处理 ---获取图片

    1.获取图片 1.相册 以隐氏intent的方式打开系统默认的图库,需要传入mimeType com.cooliris.media.Gallery 代码如下: //打开图片 Intent galler ...

最新文章

  1. android组件权限,Android中Permission权限机制的具体使用
  2. win7安装python2.7_python学习(3)-win7安装python2.7
  3. idea 快捷键 小结
  4. 函数重载与运算符重载
  5. linux cat cd,linux 文件系统命令 cat cd chmod
  6. web电商系统、电商平台WEB端交互原型模板、用户中心、会员中心、优惠券、积分、互动社区、运营推广、内容推荐、商品展示、订单流程、订单管理、售后及服务、Axure原型、rp原型、电商原型、商城系统原型
  7. metamask插件_Remix+metamask+myetherwallet+Ciper 完成主网发币(实战 十)
  8. 目标检测算法 2020_One-stage目标检测算法综述
  9. 为什么说即便是新手,也应该学习微服务?
  10. Linux保护线程,linux的线程是否受到了保护?
  11. MySQL 分区表——《高性能MySQL》
  12. Unity经验·任意位置的透视问题
  13. 数据结构与算法分析(一)基础部分与算法分析方法
  14. C++ access( )函数
  15. Field not found; typically this occurs with arrays which are not mapped as single value
  16. 读高明之《帛書老子校注》
  17. 数据结构学习笔记(第四章:串)
  18. word插入mathtype打出来的符号上浮,高于文字
  19. 总结:IOTA反驳DCI实验室提出的漏洞荒谬至极
  20. php 斜杠字符,php-如何编码包含正斜杠的查询字符串?

热门文章

  1. 计算机毕业设计Java客户关系管理平台(源码+mysql数据库+系统+lw文档)
  2. 鼠标滚轮事件java_JavaScript 事件——“事件类型”中“焦点、鼠标和滚轮事件”的注意要点...
  3. python实现贝叶斯回归_贝叶斯线性回归(Bayesian Linear Regression)
  4. 陌陌也做直播了,为什么要来抢斗鱼的饭碗?
  5. 【叫号系统】Redis ZSet结构
  6. lammps计算聚合物例子_(从examples的简单例子,到完成自己的科研课题)LAMMPS分子动力学技术与应用专题...
  7. More Moore and More than Moore
  8. linux sftp账号密码脚本传文件,关于shell:如何使用Bash脚本中的密码运行sftp命令?...
  9. MEXGroup:美联储鸽派言论兑现,短线市场或陷入震荡
  10. 并行计算之MPI(二)