美文网首页AndroidAndroid 技术收集
Android 沉浸式/透明式状态栏、导航栏

Android 沉浸式/透明式状态栏、导航栏

作者: 呱呱_ | 来源:发表于2018-02-07 17:50 被阅读44次

    前言

    Android 从4.4开始引进透明状态栏和导航栏的概念,并且在5.0进行了改进,将透明变成了半透明的效果。虽然此特性最早出现在ios,但不否认效果还是很赞的。
    至于4.4以下的手机,就不要考虑此特性了,好在4.4以下的手机份额已经非常小了。


    图1,透明式状态栏、导航栏效果图

    透明状态栏

    我们先来看一下透明状态栏的实现,两种常见效果图如下:


    图2,5.0及以上半透明效果 图3,4.4及以上全透明效果
    • 4.4及以上全透明,5.0及以上半透明
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 实现透明状态栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
    
    • 5.0及以上全透明
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
    }
    
    • 4.4及以上全透明,两者结合使用
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 实现透明状态栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }
    
    • 上述几个方法都是在没有ActionBar使用的,实测Toolbar是可以正常使用的
    // 当状态栏透明的时候,ActionBar暂时没有较好的解决方法,此方法可以将其隐藏
    // 主题不包含ActionBar,无需添加此方法
    ActionBar actionBar = getActionBar();
    if (actionBar != null) {
        actionBar.hide();
    }
    

    透明导航栏

    虚拟导航栏并不是所有的手机都有,华为的手机多比较常见,就是上图屏幕底部按钮那块区域。设置导航栏和状态栏类似:

    • 4.4及以上全透明,5.0及以上半透明
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 实现透明导航栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    
    • 5.0及以上全透明
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setNavigationBarColor(Color.TRANSPARENT);
    }
    
    • 4.4及以上全透明,使用方式类似通知栏
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setNavigationBarColor(Color.TRANSPARENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 实现透明导航栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    

    补充一个知识点: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.

    这是官方的解释,大致意思就是我们在布局的最外层设置 android:fitsSystemWindows="true",会在屏幕最上方预留出状态栏高度的padding。

    由于fitsSystemWindows属性本质上是给当前控件设置了一个padding,所以我们设置到根布局的话,会导致状态栏是透明的,并且和窗口背景一样。

    但是多数情况,我们并不在根布局设置这个属性,我们想要的无外乎是让内容沉浸在状态栏之中。所以我们经常设置在最上端的图片背景、Banner之类的,如果是Toolbar的,我们可以使用一层LinearLayout包裹,并把这个属性设置给LinearLayout,这样就可以避免Toolbar的内容下沉了。如:

     <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:fitsSystemWindows="true"
        android:orientation="vertical">
    
        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            tools:title="我是Title"/>
    
    </LinearLayout>
    

    附:图1效果完整代码

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
        window.setNavigationBarColor(Color.TRANSPARENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // 实现透明状态栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        // 实现透明导航栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    

    上述方法可以解决普通页面的透明式状态栏需求,如有复杂需求可以参考下面这些:
    Android 系统状态栏沉浸式/透明化完整解决方案
    Android 沉浸式状态栏的实现
    Android沉浸式状态栏(透明状态栏)最佳实现
    还有开源库推荐:ImmersionBar

    相关文章

      网友评论

        本文标题:Android 沉浸式/透明式状态栏、导航栏

        本文链接:https://www.haomeiwen.com/subject/imrazxtx.html