Android 状态栏样式 全面解析

来源:互联网 发布:ubuntu mongodb安装 编辑:程序博客网 时间:2024/06/03 21:53

网上已经有很多关于状态栏样式的文章,要么讲的不全,要么讲的不对,有的文章说的头头是道,但是代码是错的。所以在这里总结一下

下面以系统版本作为分界,来详细介绍状态栏的样式

源代码:https://github.com/JantHsueh/ColorfulStatusBar

一、效果图

4.4版本之前

状态栏是黑色的,无法改变

图一:
这里写图片描述

4.4及以上,5.0以下

下面的全透明和渐变透明,代码实现是一样的,因为部分定制的ROM,修改成了全透明

渐变透明:

图二:
这里写图片描述

全透明

图三:
这里写图片描述

酷派系统,MIUI,显示的是全透明的。
网上的文章,有的说使用模拟器4.4模拟器,是渐变透明。我在实际测试发现,使用4.4.2模拟器,状态栏还是黑色

5.0及以上

material design风格

图四:
这里写图片描述

二、使用到的特性

2.1、API 19 引入的新特性

Immersive Full-Screen Mode(本文不介绍,请参考官方文档)

允许用户在应用全屏的情况下,在状态栏/导航栏区域内做向内滑动,可以短暂调出状态栏和导航栏,且不会影响应用的正常全屏,短暂调出的状态栏和导航栏会呈半透明状态,可以在一段时间内或者用户与应用内元素进行互动的情况下自动隐藏。

android:windowTranslucentStatus

theme里添加style: < item name=”android:windowTranslucentStatus”> true < /item>后,状态栏的底层没有其他视图可以显示,所以toolbar上移到最顶部,看到的就是状态栏覆盖在toolbar上.如下图:

这里写图片描述
解决这个问题需要用到下面介绍的android:fitsSystemWindows

2.2、其他特性:

android:fitsSystemWindows

官方描述:
Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.

简单描述:
这个一个boolean值的内部属性,让view可以根据系统窗口(如status bar)来调整自己的布局,如果值为true,就会调整view的paingding属性来给system windows留出空间

实际效果:
当status bar为透明或半透明时(4.4以上),系统会设置view的paddingTop的值(status bar的高度),让view的内容不被上拉到状态栏(状态栏的高度是25dp)
当在不占据status bar的情况下(4.4以下)会设置paddingTop值为0(因为没有占据status bar所以不用留出空间)。

如果此时使用android:fitsSystemWindows=”true”,就可以调整内容布局,恢复到原来位置.

也可以不使用fitsSystemWindows,自己去计算padding的值,在view中设置padding。在可参考这里

三、代码实现

实现图二、图三、图四的效果

styles.xml

values/styles.xml

<resources>    <style name="BaseAppTheme" parent="Theme.AppCompat.Light.NoActionBar">        <!-- Customize your theme here. -->        <item name="colorPrimary">@color/primary</item>        <item name="colorPrimaryDark">@color/primary_dark</item>        <item name="colorAccent">#FF4081</item>    </style>    <!-- Base application theme. -->    <style name="AppTheme" parent="@style/BaseAppTheme">    </style></resources>

因为需要使用ToolBar,这里主题使用NoActionBar,隐藏ActionBar。

values-v19/styles.xml

<resources>    <!-- Base application theme. -->    <style name="AppTheme" parent="@style/BaseAppTheme">        <item name="android:windowTranslucentStatus">true</item>    </style></resources>

values-v21/styles.xml

<resources>    <!-- Base application theme. -->    <style name="AppTheme" parent="@style/BaseAppTheme">        <!--<item name="android:windowTranslucentStatus">true</item>-->    </style></resources>

布局

<LinearLayout        xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:app="http://schemas.android.com/apk/res-auto"        android:id="@+id/id_main_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical">        <android.support.v7.widget.Toolbar            android:id="@+id/id_toolbar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="?attr/colorPrimary"            android:fitsSystemWindows="true"            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>        <TextView            android:id="@+id/id_tv_content"            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="1"            android:gravity="center"            android:text="HelloWorld"            android:textSize="30sp"/>    </LinearLayout>
  • ToolBar高度设置为wrap_content
  • Toolbar 中使用android:fitsSystemWindows="true",自动设置这个view的padding,为status_bar留下空间(自动调节content视图的上边界)。

activity

public class MainActivity extends AppCompatActivity{    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);        setSupportActionBar(toolbar);        //StatusBarCompat.compat(this, getResources().getColor(R.color.status_bar_color));        //StatusBarCompat.compat(this);    }}

以上就是实现图二、图三、图四的效果的主要代码

四、自定义状态栏的颜色

md的规范

这里写图片描述

图二、图三不符合md的设计,想要让4.4机子的状态栏,看上去符合md规范,就要自定义状态栏的颜色。

自定义状态栏的颜色:

  • 4.4系统 ,把系统的状态栏设为透明,重新绘制并显示一个状态栏
  • 5.0 系统 ,使用setStatusBarColor(),设置状态栏颜色。但是使用该方法,就不能在主题中设置windowTranslucentStatus属性。否则设置的颜色不起作用
public class StatusBarCompat {    private static final int INVALID_VAL = -1;    private static final int COLOR_DEFAULT = Color.parseColor("#20000000");    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public static void compat(Activity activity, int statusColor) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            if (statusColor != INVALID_VAL) {                activity.getWindow().setStatusBarColor(statusColor);            }            return;        }        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {            int color = COLOR_DEFAULT;            ViewGroup decorViewGroup = (ViewGroup) activity.getWindow().getDecorView();            if (statusColor != INVALID_VAL) {                color = statusColor;            }            View statusBarView = new View(activity.getWindow().getContext());            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                    getStatusBarHeight(activity));            statusBarView.setBackgroundColor(color);            decorViewGroup.addView(statusBarView, lp);        }    }    public static void compat(Activity activity) {        compat(activity, INVALID_VAL);    }    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;    }}

通过往Window窗口的decorView添加一个View,让它大小与系统状态栏一样,然后设置这个view的背景颜色,就可以实现修改状态栏颜色的效果了。

使用就非常简单了,在activity中使用下面任意行代码:

StatusBarCompat.compat(this, getResources().getColor(R.color.status_bar_color));StatusBarCompat.compat(this);
  • 4.4 模拟器

这里写图片描述

  • 5.x 真机

这里写图片描述

源代码:https://github.com/JantHsueh/ColorfulStatusBar

参考:

Android开发 – android设置系统状态栏颜色(沉浸式状态栏)

Android使用fitsSystemWindows属性实现–状态栏【status_bar】各版本适配方案

Android 沉浸式状态栏攻略 让你的状态栏变色吧

Android 系统状态栏沉浸式/透明化完整解决方案

你说你看到了沉浸模式,你可能只是见到鬼了