Android 5.0 如何实现将布局的内容延伸到状态栏?

Android自5.0以后,应用可以实现类似iOS的状态栏变色功能,类似Android版的知乎。这种实现方式很简单,只需要在style里面指定颜色即可…
关注者
544
被浏览
84,459

12 个回答

不请自来,我觉得有些回答说的不是很完整,局限比较多。这个问题昨天正好研究了下,我的拙见是:


如果不需要支持 4.4,建议使用 statusBarColor

如果需要支持 4.4,简易 4.4 使用 windowTranslucentStatus;5.x 使用 statusBarColor/colorPrimaryDark

(本答案在 5.1 和 5.0 中的解决方式并不会影响软键盘和 EditText 的行为,4.4 暂时无法测试,如有朋友发现 bug 请指出,我会在回答中注明,以免其他人一起掉坑里)

下面说原因:

TranslucentStatus 在 4.4 和 5.x 上表现不同,4.4 是一层渐变的遮罩层;5.x 以上是一条半透明的遮罩层。

看上去很兼容,其实不是,在我的回答

为什么 Xperia 5.0 对部分第三方 app 状态栏显示的是 4.4 的样式? - Allan 的回答

中,第一张图就暴露了这个问题 —— 遮罩层颜色过于深,不符合 Material Design 的推荐标准。

Toolbars and status bars

Toolbars and larger color blocks should use the 500 color of the primary color of your app. The status bar should be the darker 700 tint of your primary color.

所以简易重写 v21 的 style,只将 windowTranslucnetStatus 应用于 v19。

而 v21 使用 statusBarColor 自定义符合设计指南的颜色。

如何做到 v21 上半透明的 statusBar,即在 statusbar 后显示:

1.

getWindow().setStatusBarColor()

设置半透明 statusbar

2.

getWindow()
    .getDecorView()
    .setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

因为 FLAT_LAYOUT_STABLE 和 FLAG_LAYOUT_FULLSCREEN 是伴随 translucentStatus 自动设置的,v21 上你需要手动设置(因为上述方法没用 translucentStatus)。

3. 手动调整各个 View 的位置:可以动态或缺 StatusBar 的 Height。

也可以像我一样比较懒惰

<android.support.v7.widget.Toolbar
    android:background="?attr/colorPrimary"
    android:minHeight="?attr/actionBarSize"
    android:elevation="@dimen/space_small"
    android:paddingTop="@dimen/status_bar_height/>

where

dimens.xml

<dimen name="status_bar_height">25dp</dimen>

未来的 Android M (感谢 @张启 指正)

values-v23/dimens.xml

<dimen name="status_bar_height">24dp</dimen>

为啥那么麻烦问 Google 去。

4. Enjoy

v19:

v21:


这个问题比我们想象的都复杂,建议同时阅读

@1ittlecup@张启

的两个答案:

Android 5.0 如何实现将布局的内容延伸到状态栏实? - 1ittlecup 的回答Android 5.0 如何实现将布局的内容延伸到状态栏实? - 张启的回答

综合使用需求选择合适的解决方法。

个人感觉排名第一的答案将简单问题复杂化了,其实Google在最新(截止2015年6月)的suport包已经提供了很好的支持。


UPDATED....

有图有真相,以下截图和题主描述完全一致:

练手写的app,不要在意某些细节....



简单2步就OK:

第1步:

v21的style

<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowBackground">@android:color/white</item>
        <item name="actionBarStyle">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
        <item name="android:actionBarStyle">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
    </style>
<!-以上的style和平台不相关,以下的style是v21的-->
<style name="AppTheme" parent="AppBaseTheme">
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    </style>
    
     <style name="DrawerLayoutTheme" parent="AppTheme">
       <item name="android:statusBarColor">@android:color/transparent</item>
    </style>

截图中的Activity使用DrawerLayoutTheme,以使得Drawer能显示在半透明的状态栏内。

第2步

DrawerLayout的drawer部分的根布局写成ScrimInsetsFrameLayout(android.support.design.internal.ScrimInsetsFrameLayout,在design支持包中,继承于FrameLayout,代码也很简单,但貌似是hide的,从源码复制一份出来就好了),或者直接用更规范的NavigationView(android.support.design.widget.NavigationView,NavigationView也直接继承于ScrimInsetsFrameLayout)

这2步完了就实现了题主所说的效果(也是截图中的效果)。

附上截图中Activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.mixiaoxiao.material.zhihudaily"
    android:id="@+id/main_drawerlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.mixiaoxiao.material.zhihudaily.MainActivity" >

    <!-- content -->
    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/main_coordinatorlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <!-- 省略... -->


    </android.support.design.widget.CoordinatorLayout>
    
    <!-- drawer -->

    <android.support.design.widget.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer" >
    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>