精华内容
下载资源
问答
  • Android状态栏微技巧,带你真正理解沉浸式模式

    万次阅读 多人点赞 2016-08-23 07:32:55
    记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解。 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先...

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/51763825

    本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每天都有文章更新。

    记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解。

    其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的。因为Android官方从来没有给出过沉浸式状态栏这样的命名,只有沉浸式模式(Immersive Mode)这种说法。而有些人在没有完全了解清楚沉浸模式到底是什么东西的情况下,就张冠李戴地认为一些系统提供的状态栏操作就是沉浸式的,并且还起了一个沉浸式状态栏的名字。

    比如之前就有一个QQ群友问过我,像饿了么这样的沉浸式状态栏效果该如何实现?

    这个效果其实就是让背景图片可以利用系统状态栏的空间,从而能够让背景图和状态栏融为一体。

    本篇文章当中我会教大家如何实现这样的效果,但这个真的不叫沉浸式状态栏。因此,这算是一篇技术+普及的文章吧,讲技术的同时也纠正一下大家之前错误的叫法。

    什么是沉浸式?

    先来分析一下叫错的原因吧,之所以很多人会叫错,是因为根本就不了解沉浸式是什么意思,然后就人云亦云跟着叫了。那么沉浸式到底是什么意思呢?

    根据百度百科上的定义,沉浸式就是要给用户提供完全沉浸的体验,使用户有一种置身于虚拟世界之中的感觉。

    比如说现在大热的VR就是主打的沉浸式体验。

    那么对应到Android操作系统上面,怎样才算是沉浸式体验呢?这个可能在大多数情况下都是用不到的,不过在玩游戏或者看电影的时候就非常重要了。因为游戏或者影视类的应用都希望能让用户完全沉浸在其中,享受它们提供的娱乐内容,但如果这个时候在屏幕的上方还显示一个系统状态栏的话,可能就会让用户分分钟产生跳戏的感觉。

    那么我们来看一下比较好的游戏都是怎么实现的,比如说海岛奇兵:

    海岛奇兵的这种模式就是典型的沉浸式模式,它的整个屏幕中显示都是游戏的内容,没有状态栏也没有导航栏,用户玩游戏的时候就可以完全沉浸在游戏当中,而不会被一些系统的界面元素所打扰。

    然后我们再来看一下爱奇艺的实现:

    同样也是类似的,爱奇艺将整个屏幕作为影视的展示区,用户在看电影的时候眼中就只会有电影的内容,这样就不会被其他一些无关的东西所分心。

    这才是沉浸式模式的真正含义,而所谓的什么沉浸式状态栏纯粹就是在瞎叫,完全都没搞懂“沉浸式” 这三个字是什么意思。

    不过虽然听上去好像是很高大上的沉浸式效果,实际看上去貌似就是将内容全屏化了而已嘛。没错,Android沉浸式模式的本质就是全屏化,不过我们今天的内容并不仅限于此,因为还要实现饿了么那样的状态栏效果。那么下面我们就开始来一步步学习吧。

    隐藏状态栏

    一个Android应用程序的界面上其实是有很多系统元素的,观察下图:

    可以看到,有状态栏、ActionBar、导航栏等。而打造沉浸式模式的用户体验,就是要将这些系统元素全部隐藏,只留下主体内容部分。

    比如说我现在新建了一个空项目,然后修改布局文件中的代码,在里面加入一个ImageView,如下所示:

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/bg"
            android:scaleType="centerCrop" />
    
    </RelativeLayout>

    这里将ImageView的宽和高都设置成match_parent,让图片充满屏幕。现在运行一下程序,效果如下图所示。

    如果你将图片理解成游戏或者电影界面的话,那这个体验离沉浸式就差得太远了,至少状态栏和ActionBar得要隐藏起来了吧?没关系,我们一步步进行优化,并且在优化中学习。

    隐藏状态栏和ActionBar的方式在4.1系统之上和4.1系统之下还是不一样的,这里我就不准备考虑4.1系统之下的兼容性了,因为过于老的系统根本就没有提供沉浸式体验的支持。

    修改MainActivity中的代码,如下所示:

    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(option);
            ActionBar actionBar = getSupportActionBar();
            actionBar.hide();
        }
    }

    这里先调用getWindow().getDecorView()方法获取到了当前界面的DecorView,然后调用它的setSystemUiVisibility()方法来设置系统UI元素的可见性。其中,SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是会将状态栏隐藏。另外,根据Android的设计建议,ActionBar是不应该独立于状态栏而单独显示的,因此状态栏如果隐藏了,我们同时也需要调用ActionBar的hide()方法将ActionBar也进行隐藏。

    现在重新运行一下程序,效果如下图所示。

    这样看上去就有点沉浸式效果的模样了。

    虽说这才是正统的沉浸式含义,但有些朋友可能想实现的就是饿了么那样的状态栏效果,而不是直接把整个系统状态栏给隐藏掉,那么又该如何实现呢?

    其实也很简单,只需要借助另外一种UI Flag就可以了,如下所示:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    首先需要注意,饿了么这样的效果是只有5.0及以上系统才支持,因此这里先进行了一层if判断,只有系统版本大于或等于5.0的时候才会执行下面的代码。

    接下来我们使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和SYSTEM_UI_FLAG_LAYOUT_STABLE,注意两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间,最后再调用Window的setStatusBarColor()方法将状态栏设置成透明色就可以了。

    现在重新运行一下代码,效果如下图所示。

    可以看到,类似于饿了么的状态栏效果就成功实现了。

    再声明一次,这种效果不叫沉浸式状态栏,也完全没有沉浸式状态栏这种说法,我们估且可以把它叫做透明状态栏效果吧。

    隐藏导航栏

    现在我们已经成功实现隐藏状态栏的效果了,不过屏幕下方的导航栏还比较刺眼,接下来我们就学习一下如何将导航栏也进行隐藏。

    其实实现的原理都是一样的,隐藏导航栏也就是使用了不同的UI Flag而已,修改MainActivity中的代码,如下所示:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(option);
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    这里我们同时使用了SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,这样就可以将状态栏和导航栏同时隐藏了。现在重新运行一下程序,效果如图所示。

    这次看上去好像终于是完全全屏化了,但其实上这离真正的沉浸式模式还差得比较远,因为在这种模式下,我们触摸屏幕的任意位置都会退出全屏。

    这显然不是我们想要的效果,因此这种模式的使用场景比较有限。

    除了隐藏导航栏之外,我们同样也可以实现和刚才透明状态栏类似的效果,制作一个透明导航栏:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setNavigationBarColor(Color.TRANSPARENT);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    这里使用了SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,表示会让应用的主体内容占用系统导航栏的空间,然后又调用了setNavigationBarColor()方法将导航栏设置成透明色。现在重新运行一下程序,效果如下图所示。

    真正的沉浸式模式

    虽说沉浸式导航栏这个东西是被很多人误叫的一种称呼,但沉浸式模式的确是存在的。那么我们如何才能实现像海岛奇兵以及爱奇艺那样的沉浸式模式呢?

    首先你应该确定自己是否真的需要这个功能,因为除了像游戏或者视频软件这类特殊的应用,大多数的应用程序都是用不到沉浸式模式的。

    当你确定要使用沉浸式模式,那么只需要重写Activity的onWindowFocusChanged()方法,然后加入如下逻辑即可:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            if (hasFocus && Build.VERSION.SDK_INT >= 19) {
                View decorView = getWindow().getDecorView();
                decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            }
        }
    
    }

    沉浸式模式的UI Flag就这些,也没什么好解释的,如果你需要实现沉浸式模式,直接将上面的代码复制过去就行了。需要注意的是,只有在Android 4.4及以上系统才支持沉浸式模式,因此这里也是加入了if判断。

    另外,为了让我们的界面看上去更像是游戏,这里我将MainActivity设置成了横屏模式:

    <activity android:name=".MainActivity" 
              android:screenOrientation="landscape">
        ...
    </activity>

    这样我们就实现类似于海岛奇兵和爱奇艺的沉浸式模式效果了,如下图所示。

    可以看到,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态。

    这就是最标准的沉浸式模式。


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • 实现4.4以后的状态栏与app的导航栏颜色相同,android沉浸式状态栏、变色状态栏、透明状态栏、修改状态栏颜色及透明。
  • Android 沉浸式状态栏攻略 让你的状态栏变色吧

    万次阅读 多人点赞 2015-09-22 09:21:03
    一、概述近期注意到QQ新版使用了沉浸式状态栏,ok,先声明一下:本篇博客效果下图:关于这个状态栏变色到底叫「Immersive Mode」/「Translucent Bars」有兴趣可以去 为什么在国内会有很多用户把 「透明

    转载请标明出处:
    http://blog.csdn.net/lmj623565791/article/details/48649563
    本文出自:【张鸿洋的博客】

    一、概述

    近期注意到QQ新版使用了沉浸式状态栏,ok,先声明一下:本篇博客效果下图:

    20150922091410975

    关于这个状态栏变色到底叫「Immersive Mode」/「Translucent Bars」有兴趣可以去 为什么在国内会有很多用户把 「透明栏」(Translucent Bars)称作 「沉浸式顶栏」?上面了解了解,请勿指点我说的博文标题起得不对,thx。

    恩,接下来正题。

    首先只有大于等于4.4版本支持这个半透明状态栏的效果,但是4.4和5.0的显示效果有一定的差异,所有本篇博文内容为:

    • 如何实现半透明状态栏效果在大于4.4版本之上。
    • 如何让4.4的效果与5.0的效果尽可能一致。

    看了不少参考文章,都介绍到这个库,大家可以了解:SystemBarTint

    不过本篇博文并未基于此库,自己想了个hack,对于此库源码有空再看了。


    二、效果图

    先贴下效果图,以便和实现过程中做下对比

    • 4.4 模拟器

    20150922091443734

    • 5.x 真机

    20150922091513487

    [new]贴个如果顶部是图片的效果图,其实是一样的,为了方便我就放侧栏的顶部了。

    lalala.gif

    稍等,csdn图片服务器异常…

    ok,有了效果图之后就开始看实现了。


    三、实现半透明状态栏

    因为本例使用了NavigationView,所以布局代码稍多,当然如果你不需要,可以自己进行筛减。

    注意引入相关依赖:

     compile 'com.android.support:appcompat-v7:22.2.1'
     compile 'com.android.support:support-v4:22.2.1'
     compile 'com.android.support:design:22.2.0'

    (一)colors.xml 和 styles.xml

    首先我们定义几个颜色:

    res/values/color.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="primary">#FF03A9F4</color>
        <color name="primary_dark">#FF0288D1</color>
        <color name="status_bar_color">@color/primary_dark</color>
    </resources>

    下面定义几个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>

    values-v19

    <resources>
    
        <style name="AppTheme" parent="@style/BaseAppTheme">
            <item name="android:windowTranslucentStatus">true</item>
        </style>
    </resources>
    

    ok,这个没撒说的。注意我们的主题是基于NoActionBar的,android:windowTranslucentStatus这个属性是v19开始引入的。

    (二)布局文件

    activity_main.xml

    <android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    
    
        <LinearLayout
            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>
    
    
        <android.support.design.widget.NavigationView
            android:id="@+id/id_nv_menu"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/header_just_username"
            app:menu="@menu/menu_drawer"
            />
    </android.support.v4.widget.DrawerLayout>
    

    DrawerLayout内部一个LinearLayout作为内容区域,一个NavigationView作为菜单。
    注意下Toolbar的高度设置为wrap_content。

    然后我们的NavigationView中又依赖一个布局文件和一个menu的文件。

    header_just_username.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="192dp"
                    android:background="?attr/colorPrimaryDark"
                    android:orientation="vertical"
                    android:padding="16dp"
                    android:fitsSystemWindows="true"
                    android:theme="@style/ThemeOverlay.AppCompat.Dark">
    
        <TextView
            android:id="@+id/id_link"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="16dp"
            android:text="http://blog.csdn.net/lmj623565791"/>
    
        <TextView
            android:id="@+id/id_username"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@id/id_link"
            android:text="Zhang Hongyang"/>
    
        <ImageView
            android:layout_width="72dp"
            android:layout_height="72dp"
            android:layout_above="@id/id_username"
            android:layout_marginBottom="16dp"
            android:src="@mipmap/ic_launcher"/>
    
    
    </RelativeLayout>

    menu的文件就不贴了,更加详细的可以去参考Android 自己实现 NavigationView [Design Support Library(1)]

    大体看完布局文件以后,有几个点要特别注意:

    • ToolBar高度设置为wrap_content
    • ToolBar添加属性android:fitsSystemWindows="true"
    • header_just_username.xml的跟布局RelativeLayout,添加属性android:fitsSystemWindows="true"

    android:fitsSystemWindows这个属性,主要是通过调整当前设置这个属性的view的padding去为我们的status_bar留下空间。

    根据上面的解释,如果你不写,那么状态栏和Toolbar就会有挤一块的感觉了,类似会这样:

    20150922091617868

    ok,最后看下代码。

    (三)Activity的代码

    package com.zhy.colorfulstatusbar;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    
    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);
        }
    
    }
    

    没撒说的,就是setSupportActionBar。

    那么现在4.4的效果图是:

    20150922091636754

    其实还不错,有个渐变的效果。

    现在5.x的效果:

    20150922094815752

    可以看到5.x默认并非是一个渐变的效果,类似是一个深一点的颜色。

    在看看我们md的规范

    20150427034747930

    状态栏应该是一个比Toolbar背景色,稍微深一点的颜色。

    这么看来,我们还是有必要去为4.4做点适配工作,让其竟可能和5.x显示效果一致,或者说尽可能符合md的规范。


    四、调整4.4的显示方案

    那么问题来了?如何做呢?

    咱们这么看,4.4之后加入windowTranslucentStatus的属性之后,也就是我们可以用到状态栏的区域了。

    既然我们可以用到这块区域,那么我们只要在根布局去设置一个与状态栏等高的View,设置背景色为我们期望的颜色就可以了。

    于是有了以下的代码:

    package com.zhy.colorfulstatusbar;
    
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Color;
    import android.os.Build;
    import android.view.View;
    import android.view.ViewGroup;
    
    /**
     * Created by zhy on 15/9/21.
     */
    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 contentView = (ViewGroup) activity.findViewById(android.R.id.content);
                if (statusColor != INVALID_VAL)
                {
                    color = statusColor;
                }
                View statusBarView = new View(activity);
                ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        getStatusBarHeight(activity));
                statusBarView.setBackgroundColor(color);
                contentView.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;
        }
    }
    

    代码的思路很简单,根据Activity找到android.R.content,在其中添加一个View(高度为statusbarHeight,背景色为我们设置的颜色,默认为半透明的黑色)。

    那么只需要在Activity里面去写上:

    StatusBarCompat.compat(this);

    就可以了。

    如果你希望自己设置状态看颜色,那么就用这个方法:

    StatusBarCompat.compat(this, getResources().getColor(R.color.status_bar_color));

    这样的话我们就解决了4.4到5.x的适配问题,一行代码解决,感觉还是不错的。

    最后提一下,对于5.0由于提供了setStatusBarColor去设置状态栏颜色,但是这个方法不能在主题中设置windowTranslucentStatus属性。所以,可以编写一个value-v21文件夹,里面styles.xml写入:

    <resources>
        <!-- Base application theme. -->
        <style name="AppTheme" parent="@style/BaseAppTheme">
        </style>
    </resources>
    

    其实就是不要有windowTranslucentStatus属性。

    接下来,对于默认的效果就不测试了,参考上面的效果图。

    我们测试个设置状态栏颜色的,我们这里设置个红色。

    • 4.4 模拟器

    20150922091706192

    • 5.x 真机

    20150922091721370

    ok,这样就结束啦~~

    源码地址:https://github.com/hongyangAndroid/ColorfulStatusBar


    欢迎关注我的微博:
    http://weibo.com/u/3165018720


    群号:463081660,欢迎入群

    微信公众号:hongyangAndroid
    (欢迎关注,第一时间推送博文信息)
    1422600516_2905.jpg

    参考

    展开全文
  • 今天总结一下状态栏的使用,当然也是参考别人的。但是总归自己得试试,然后把常用的几种情况记下来,因为这些东西是死的,下次拿过来就可以用。 一. 沉浸式状态栏 :Android 5.0以上才会支持沉浸式状态栏效果。 ...

    今天总结一下状态栏的使用,当然也是参考别人的。但是总归自己得试试,然后把常用的几种情况记下来,因为这些东西是死的,下次拿过来就可以用。

    一. 沉浸式状态栏  :Android 5.0以上才会支持沉浸式状态栏效果。 下面就建立一个默认的项目。1.状态栏(背景色是蓝色,字体图标是白色的)2.ActionBar,一般都不用的 3.内容 4.虚拟键。       所谓沉浸式状态栏就是只有3着哭泣区域占据整个屏幕,如爱奇艺全屏模式,玩王者荣耀的时候。但是一般情况下我们开发的APP都不会用到的,所以那里的沉浸式状态栏就是:去掉ActionBar,内容区占据状态栏(他俩重合),并且状态栏的透明或者半透明状态。行了直接上代码吧。

    1.完全的沉浸式状态栏(下图):

    代码:

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus && Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION  
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
    }

    图1

    2.状态栏透明+底部导航栏透明+主体内容充满整个屏幕+去掉ActionBar(这种可以某些布局会影响操作  使用不多)

    代码:

    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setNavigationBarColor(Color.TRANSPARENT);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();  

    图2:

    3.状态栏透明+主体内容上部延伸到状态栏+去掉ActionBar

    代码:

    if (Build.VERSION.SDK_INT >= 21) {
        View decorView = getWindow().getDecorView();
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        decorView.setSystemUiVisibility(option);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    图3.

    注意: 1.使用沉浸式状态栏一定不要在Activity中的xml根布局中使用:

    android:fitsSystemWindows="true"

    2.如果不想在代码里面去掉ActionBar可以直接在style中修改Theme为:

    parent="Theme.AppCompat.Light.NoActionBar"

    二.如何修改状态栏的背景颜色和字体,图表颜色

    1.状态栏字体颜色,我只接上工具类代码以及相关代码:

    StateUtils:直接使用的工具类

    SystemBarTintManager:修改状态颜色的辅助类
    RomUtils:设置状态栏字体时候 怼不通机型进行适配

    使用:

    //设置状态蓝的颜色,也可以给颜色本身设置透明度,自己试试
    StateUtils.setStatusBarColor(this, R.color.colorAccents);
    //设置状态栏字体颜色,true:代表黑色,false代表白色
    StateUtils.setLightStatusBar(this, true);
    public class StateUtils {
    
        /**
         * 1.修改状态栏颜色,支持4.4以上版本
         * @param activity
         * @param colorId
         */
        public static void setStatusBarColor(Activity activity, int colorId) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Window window = activity.getWindow();
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(activity.getResources().getColor(colorId));
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                //使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
                transparencyBar(activity);
                SystemBarTintManager tintManager = new SystemBarTintManager(activity);
                tintManager.setStatusBarTintEnabled(true);
                tintManager.setStatusBarTintResource(colorId);
            }
        }
    
    
    
        /**
         *  2.修改状态栏文字颜色,这里小米,魅族区别对待。
         */
        public static void setLightStatusBar(final Activity activity, final boolean dark) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                switch (RomUtils.getLightStatusBarAvailableRomType()) {
                    case RomUtils.AvailableRomType.MIUI:
                        MIUISetStatusBarLightMode(activity, dark);
                        break;
    
                    case RomUtils.AvailableRomType.FLYME:
                        setFlymeLightStatusBar(activity, dark);
    
                        break;
    
                    case RomUtils.AvailableRomType.ANDROID_NATIVE:
                        setAndroidNativeLightStatusBar(activity, dark);
                        break;
    
                }
            }
        }
    
    
        /**
         * 小米修改状态栏字体
         * @param activity
         * @param dark
         * @return
         */
        public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
            boolean result = false;
            Window window = activity.getWindow();
            if (window != null) {
                Class clazz = window.getClass();
                try {
                    int darkModeFlag = 0;
                    Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                    Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                    darkModeFlag = field.getInt(layoutParams);
                    Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                    if (dark) {
                        extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
                    } else {
                        extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                    }
                    result = true;
    
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && RomUtils.isMiUIV7OrAbove()) {
                        //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
                        if (dark) {
                            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                        } else {
                            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                        }
                    }
                } catch (Exception e) {
    
                }
            }
            return result;
        }
    
        /**
         * 魅族修改字体颜色
         * @param activity
         * @param dark
         * @return
         */
        private static boolean setFlymeLightStatusBar(Activity activity, boolean dark) {
            boolean result = false;
            if (activity != null) {
                try {
                    WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
                    Field darkFlag = WindowManager.LayoutParams.class
                            .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                    Field meizuFlags = WindowManager.LayoutParams.class
                            .getDeclaredField("meizuFlags");
                    darkFlag.setAccessible(true);
                    meizuFlags.setAccessible(true);
                    int bit = darkFlag.getInt(null);
                    int value = meizuFlags.getInt(lp);
                    if (dark) {
                        value |= bit;
                    } else {
                        value &= ~bit;
                    }
                    meizuFlags.setInt(lp, value);
                    activity.getWindow().setAttributes(lp);
                    result = true;
                } catch (Exception e) {
                }
            }
            return result;
        }
    
        /**
         * 谷歌原生方式修改
         * @param activity
         * @param dark
         */
        private static void setAndroidNativeLightStatusBar(Activity activity, boolean dark) {
            View decor = activity.getWindow().getDecorView();
            if (dark) {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            }
        }
    
        /**
         * 设置状态栏透明,启用全屏模式
         * @param activity
         */
        @TargetApi(19)
        public static void transparencyBar(Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Window window = activity.getWindow();
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.TRANSPARENT);
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                Window window = activity.getWindow();
                window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        }
    
    
    }
    /**
     * Class to manage status and navigation bar tint effects when using KitKat
     * translucent system UI modes.
     * 修改状态栏颜色的辅助类 
     *
     */
    public class SystemBarTintManager {
    
        static {
            // Android allows a system property to override the presence of the navigation bar.
            // Used by the emulator.
            // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                try {
                    Class c = Class.forName("android.os.SystemProperties");
                    Method m = c.getDeclaredMethod("get", String.class);
                    m.setAccessible(true);
                    sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
                } catch (Throwable e) {
                    sNavBarOverride = null;
                }
            }
        }
    
    
        /**
         * The default system bar tint color value.
         */
        public static final int DEFAULT_TINT_COLOR = 0x99000000;
    
        private static String sNavBarOverride;
    
        private final SystemBarConfig mConfig;
        private boolean mStatusBarAvailable;
        private boolean mNavBarAvailable;
        private boolean mStatusBarTintEnabled;
        private boolean mNavBarTintEnabled;
        private View mStatusBarTintView;
        private View mNavBarTintView;
    
        /**
         * Constructor. Call this in the host activity onCreate method after its
         * content view has been set. You should always create new instances when
         * the host activity is recreated.
         *
         * @param activity The host activity.
         */
        @TargetApi(19)
        public SystemBarTintManager(Activity activity) {
    
            Window win = activity.getWindow();
            ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                // check theme attrs
                int[] attrs = {android.R.attr.windowTranslucentStatus,
                        android.R.attr.windowTranslucentNavigation};
                TypedArray a = activity.obtainStyledAttributes(attrs);
                try {
                    mStatusBarAvailable = a.getBoolean(0, false);
                    mNavBarAvailable = a.getBoolean(1, false);
                } finally {
                    a.recycle();
                }
    
                // check window flags
                WindowManager.LayoutParams winParams = win.getAttributes();
                int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
                if ((winParams.flags & bits) != 0) {
                    mStatusBarAvailable = true;
                }
                bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
                if ((winParams.flags & bits) != 0) {
                    mNavBarAvailable = true;
                }
            }
    
            mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
            // device might not have virtual navigation keys
            if (!mConfig.hasNavigtionBar()) {
                mNavBarAvailable = false;
            }
    
            if (mStatusBarAvailable) {
                setupStatusBarView(activity, decorViewGroup);
            }
            if (mNavBarAvailable) {
                setupNavBarView(activity, decorViewGroup);
            }
    
        }
    
        /**
         * Enable tinting of the system status bar.
         *
         * If the platform is running Jelly Bean or earlier, or translucent system
         * UI modes have not been enabled in either the theme or via window flags,
         * then this method does nothing.
         *
         * @param enabled True to enable tinting, false to disable it (default).
         */
        public void setStatusBarTintEnabled(boolean enabled) {
            mStatusBarTintEnabled = enabled;
            if (mStatusBarAvailable) {
                mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
            }
        }
    
        /**
         * Enable tinting of the system navigation bar.
         *
         * If the platform does not have soft navigation keys, is running Jelly Bean
         * or earlier, or translucent system UI modes have not been enabled in either
         * the theme or via window flags, then this method does nothing.
         *
         * @param enabled True to enable tinting, false to disable it (default).
         */
        public void setNavigationBarTintEnabled(boolean enabled) {
            mNavBarTintEnabled = enabled;
            if (mNavBarAvailable) {
                mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
            }
        }
    
        /**
         * Apply the specified color tint to all system UI bars.
         *
         * @param color The color of the background tint.
         */
        public void setTintColor(int color) {
            setStatusBarTintColor(color);
            setNavigationBarTintColor(color);
        }
    
        /**
         * Apply the specified drawable or color resource to all system UI bars.
         *
         * @param res The identifier of the resource.
         */
        public void setTintResource(int res) {
            setStatusBarTintResource(res);
            setNavigationBarTintResource(res);
        }
    
        /**
         * Apply the specified drawable to all system UI bars.
         *
         * @param drawable The drawable to use as the background, or null to remove it.
         */
        public void setTintDrawable(Drawable drawable) {
            setStatusBarTintDrawable(drawable);
            setNavigationBarTintDrawable(drawable);
        }
    
        /**
         * Apply the specified alpha to all system UI bars.
         *
         * @param alpha The alpha to use
         */
        public void setTintAlpha(float alpha) {
            setStatusBarAlpha(alpha);
            setNavigationBarAlpha(alpha);
        }
    
        /**
         * Apply the specified color tint to the system status bar.
         *
         * @param color The color of the background tint.
         */
        public void setStatusBarTintColor(int color) {
            if (mStatusBarAvailable) {
                mStatusBarTintView.setBackgroundColor(color);
            }
        }
    
        /**
         * Apply the specified drawable or color resource to the system status bar.
         *
         * @param res The identifier of the resource.
         */
        public void setStatusBarTintResource(int res) {
            if (mStatusBarAvailable) {
                mStatusBarTintView.setBackgroundResource(res);
            }
        }
    
        /**
         * Apply the specified drawable to the system status bar.
         *
         * @param drawable The drawable to use as the background, or null to remove it.
         */
        @SuppressWarnings("deprecation")
        public void setStatusBarTintDrawable(Drawable drawable) {
            if (mStatusBarAvailable) {
                mStatusBarTintView.setBackgroundDrawable(drawable);
            }
        }
    
        /**
         * Apply the specified alpha to the system status bar.
         *
         * @param alpha The alpha to use
         */
        @TargetApi(11)
        public void setStatusBarAlpha(float alpha) {
            if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                mStatusBarTintView.setAlpha(alpha);
            }
        }
    
        /**
         * Apply the specified color tint to the system navigation bar.
         *
         * @param color The color of the background tint.
         */
        public void setNavigationBarTintColor(int color) {
            if (mNavBarAvailable) {
                mNavBarTintView.setBackgroundColor(color);
            }
        }
    
        /**
         * Apply the specified drawable or color resource to the system navigation bar.
         *
         * @param res The identifier of the resource.
         */
        public void setNavigationBarTintResource(int res) {
            if (mNavBarAvailable) {
                mNavBarTintView.setBackgroundResource(res);
            }
        }
    
        /**
         * Apply the specified drawable to the system navigation bar.
         *
         * @param drawable The drawable to use as the background, or null to remove it.
         */
        @SuppressWarnings("deprecation")
        public void setNavigationBarTintDrawable(Drawable drawable) {
            if (mNavBarAvailable) {
                mNavBarTintView.setBackgroundDrawable(drawable);
            }
        }
    
        /**
         * Apply the specified alpha to the system navigation bar.
         *
         * @param alpha The alpha to use
         */
        @TargetApi(11)
        public void setNavigationBarAlpha(float alpha) {
            if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                mNavBarTintView.setAlpha(alpha);
            }
        }
    
        /**
         * Get the system bar configuration.
         *
         * @return The system bar configuration for the current device configuration.
         */
        public SystemBarConfig getConfig() {
            return mConfig;
        }
    
        /**
         * Is tinting enabled for the system status bar?
         *
         * @return True if enabled, False otherwise.
         */
        public boolean isStatusBarTintEnabled() {
            return mStatusBarTintEnabled;
        }
    
        /**
         * Is tinting enabled for the system navigation bar?
         *
         * @return True if enabled, False otherwise.
         */
        public boolean isNavBarTintEnabled() {
            return mNavBarTintEnabled;
        }
    
        private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
            mStatusBarTintView = new View(context);
            LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
            params.gravity = Gravity.TOP;
            if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
                params.rightMargin = mConfig.getNavigationBarWidth();
            }
            mStatusBarTintView.setLayoutParams(params);
            mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
            mStatusBarTintView.setVisibility(View.GONE);
            decorViewGroup.addView(mStatusBarTintView);
        }
    
        private void setupNavBarView(Context context, ViewGroup decorViewGroup) {
            mNavBarTintView = new View(context);
            LayoutParams params;
            if (mConfig.isNavigationAtBottom()) {
                params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
                params.gravity = Gravity.BOTTOM;
            } else {
                params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);
                params.gravity = Gravity.RIGHT;
            }
            mNavBarTintView.setLayoutParams(params);
            mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
            mNavBarTintView.setVisibility(View.GONE);
            decorViewGroup.addView(mNavBarTintView);
        }
    
        /**
         * Class which describes system bar sizing and other characteristics for the current
         * device configuration.
         *
         */
        public static class SystemBarConfig {
    
            private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
            private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
            private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
            private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
            private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
    
            private final boolean mTranslucentStatusBar;
            private final boolean mTranslucentNavBar;
            private final int mStatusBarHeight;
            private final int mActionBarHeight;
            private final boolean mHasNavigationBar;
            private final int mNavigationBarHeight;
            private final int mNavigationBarWidth;
            private final boolean mInPortrait;
            private final float mSmallestWidthDp;
    
            private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
                Resources res = activity.getResources();
                mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
                mSmallestWidthDp = getSmallestWidthDp(activity);
                mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
                mActionBarHeight = getActionBarHeight(activity);
                mNavigationBarHeight = getNavigationBarHeight(activity);
                mNavigationBarWidth = getNavigationBarWidth(activity);
                mHasNavigationBar = (mNavigationBarHeight > 0);
                mTranslucentStatusBar = translucentStatusBar;
                mTranslucentNavBar = traslucentNavBar;
            }
    
            @TargetApi(14)
            private int getActionBarHeight(Context context) {
                int result = 0;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    TypedValue tv = new TypedValue();
                    context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
                    result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
                }
                return result;
            }
    
            @TargetApi(14)
            private int getNavigationBarHeight(Context context) {
                Resources res = context.getResources();
                int result = 0;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    if (hasNavBar(context)) {
                        String key;
                        if (mInPortrait) {
                            key = NAV_BAR_HEIGHT_RES_NAME;
                        } else {
                            key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
                        }
                        return getInternalDimensionSize(res, key);
                    }
                }
                return result;
            }
    
            @TargetApi(14)
            private int getNavigationBarWidth(Context context) {
                Resources res = context.getResources();
                int result = 0;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    if (hasNavBar(context)) {
                        return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
                    }
                }
                return result;
            }
    
            @TargetApi(14)
            private boolean hasNavBar(Context context) {
                Resources res = context.getResources();
                int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
                if (resourceId != 0) {
                    boolean hasNav = res.getBoolean(resourceId);
                    // check override flag (see static block)
                    if ("1".equals(sNavBarOverride)) {
                        hasNav = false;
                    } else if ("0".equals(sNavBarOverride)) {
                        hasNav = true;
                    }
                    return hasNav;
                } else { // fallback
                    return !ViewConfiguration.get(context).hasPermanentMenuKey();
                }
            }
    
            private int getInternalDimensionSize(Resources res, String key) {
                int result = 0;
                int resourceId = res.getIdentifier(key, "dimen", "android");
                if (resourceId > 0) {
                    result = res.getDimensionPixelSize(resourceId);
                }
                return result;
            }
    
            @SuppressLint("NewApi")
            private float getSmallestWidthDp(Activity activity) {
                DisplayMetrics metrics = new DisplayMetrics();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
                } else {
                    // TODO this is not correct, but we don't really care pre-kitkat
                    activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
                }
                float widthDp = metrics.widthPixels / metrics.density;
                float heightDp = metrics.heightPixels / metrics.density;
                return Math.min(widthDp, heightDp);
            }
    
            /**
             * Should a navigation bar appear at the bottom of the screen in the current
             * device configuration? A navigation bar may appear on the right side of
             * the screen in certain configurations.
             *
             * @return True if navigation should appear at the bottom of the screen, False otherwise.
             */
            public boolean isNavigationAtBottom() {
                return (mSmallestWidthDp >= 600 || mInPortrait);
            }
    
            /**
             * Get the height of the system status bar.
             *
             * @return The height of the status bar (in pixels).
             */
            public int getStatusBarHeight() {
                return mStatusBarHeight;
            }
    
            /**
             * Get the height of the action bar.
             *
             * @return The height of the action bar (in pixels).
             */
            public int getActionBarHeight() {
                return mActionBarHeight;
            }
    
            /**
             * Does this device have a system navigation bar?
             *
             * @return True if this device uses soft key navigation, False otherwise.
             */
            public boolean hasNavigtionBar() {
                return mHasNavigationBar;
            }
    
            /**
             * Get the height of the system navigation bar.
             *
             * @return The height of the navigation bar (in pixels). If the device does not have
             * soft navigation keys, this will always return 0.
             */
            public int getNavigationBarHeight() {
                return mNavigationBarHeight;
            }
    
            /**
             * Get the width of the system navigation bar when it is placed vertically on the screen.
             *
             * @return The width of the navigation bar (in pixels). If the device does not have
             * soft navigation keys, this will always return 0.
             */
            public int getNavigationBarWidth() {
                return mNavigationBarWidth;
            }
    
            /**
             * Get the layout inset for any system UI that appears at the top of the screen.
             *
             * @param withActionBar True to include the height of the action bar, False otherwise.
             * @return The layout inset (in pixels).
             */
            public int getPixelInsetTop(boolean withActionBar) {
                return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
            }
    
            /**
             * Get the layout inset for any system UI that appears at the bottom of the screen.
             *
             * @return The layout inset (in pixels).
             */
            public int getPixelInsetBottom() {
                if (mTranslucentNavBar && isNavigationAtBottom()) {
                    return mNavigationBarHeight;
                } else {
                    return 0;
                }
            }
    
            /**
             * Get the layout inset for any system UI that appears at the right of the screen.
             *
             * @return The layout inset (in pixels).
             */
            public int getPixelInsetRight() {
                if (mTranslucentNavBar && !isNavigationAtBottom()) {
                    return mNavigationBarWidth;
                } else {
                    return 0;
                }
            }
    
        }
    

     

    /**
     * 设置状态栏时候 怼不通机型进行适配
     */
    public class RomUtils {
    
        class AvailableRomType {
            public static final int MIUI = 1;
            public static final int FLYME = 2;
            public static final int ANDROID_NATIVE = 3;
            public static final int NA = 4;
        }
    
        public static int getLightStatusBarAvailableRomType() {
            //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错
            if (isMiUIV7OrAbove()) {
                return AvailableRomType.ANDROID_NATIVE;
            }
    
            if (isMiUIV6OrAbove()) {
                return AvailableRomType.MIUI;
            }
    
            if (isFlymeV4OrAbove()) {
                return AvailableRomType.FLYME;
            }
    
            if (isAndroidMOrAbove()) {
                return AvailableRomType.ANDROID_NATIVE;
            }
    
            return AvailableRomType.NA;
        }
    
        //Flyme V4的displayId格式为 [Flyme OS 4.x.x.xA]
        //Flyme V5的displayId格式为 [Flyme 5.x.x.x beta]
        private static boolean isFlymeV4OrAbove() {
            String displayId = Build.DISPLAY;
            if (!TextUtils.isEmpty(displayId) && displayId.contains("Flyme")) {
                String[] displayIdArray = displayId.split(" ");
                for (String temp : displayIdArray) {
                    //版本号4以上,形如4.x.
                    if (temp.matches("^[4-9]\\.(\\d+\\.)+\\S*")) {
                        return true;
                    }
                }
            }
            return false;
        }
    
        //Android Api 23以上
        private static boolean isAndroidMOrAbove() {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
        }
    
        private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
    
        private static boolean isMiUIV6OrAbove() {
            try {
                final Properties properties = new Properties();
                properties.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
                String uiCode = properties.getProperty(KEY_MIUI_VERSION_CODE, null);
                if (uiCode != null) {
                    int code = Integer.parseInt(uiCode);
                    return code >= 4;
                } else {
                    return false;
                }
    
            } catch (final Exception e) {
                return false;
            }
    
        }
    
        static boolean isMiUIV7OrAbove() {
            try {
                final Properties properties = new Properties();
                properties.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
                String uiCode = properties.getProperty(KEY_MIUI_VERSION_CODE, null);
                if (uiCode != null) {
                    int code = Integer.parseInt(uiCode);
                    return code >= 5;
                } else {
                    return false;
                }
    
            } catch (final Exception e) {
                return false;
            }
    
        }
    
    }

    好了 ,也就这些了 。  自己可以复制出去试试就好了。

    总结:

    一般情况首页的那几个Fragment 使用的沉浸式较多一些:透明状态栏+黑色      或者透明状态栏+白色

    业务模块中: 可以统一设置状态栏颜色,以及字体颜色。

    展开全文
  • 沉浸式状态栏:,状态栏隐藏,在手指做了相关操作后,状态栏显示出来,例如视频播放器,在播放视频时是隐藏状态栏的,但是点击屏幕的时候,状态栏会显示出来,再例如文本阅读器,在阅读的时候是全屏的,然后从屏幕...

    Android基础汇总

    @[toc]

    #1 概念:

    变色状态栏(透明状态栏):指的是状态栏与导航栏颜色相同,或者透明

    沉浸式状态栏:,状态栏隐藏,在手指做了相关操作后,状态栏显示出来,例如视频播放器,在播放视频时是隐藏状态栏的,但是点击屏幕的时候,状态栏会显示出来,再例如文本阅读器,在阅读的时候是全屏的,然后从屏幕上方下滑或者下方上划,虚拟键和状态栏出现了,但却是直接覆盖在程序文字上的,这是所谓的沉浸式状态栏。 

     

    #2 效果图

    (1)透明效果:

    a. android 4.4以下不起作用(注意兼容):

    aa

     

    b. 4.4和5.0以上(5.0以上要调用另外的标记重新设置Flag,不然状态栏会有灰色的透明阴影效果)

    aa

     

     

    (2)修改状态栏字体颜色(6.0以下不起效果,不能直接设置,而是通过两种模式,魅族、小米有对应暴露方法,但本文得考虑所有机型)

    aa

    修改之后:

    aa

     

     

    #3Demo地址:

    http://download.csdn.net/detail/baopengjian/9806226

     

    #4 代码:

    (1)布局

    <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
    xmlns:tools="http://schemas.android.com/tools"
    
    android:id="@+id/activity_main"
    
    android:layout_width="match_parent"
    
    android:layout_height="match_parent"
    
    android:fitsSystemWindows="false"
    
    tools:context="transparentstatus.pbj.net.transparentstatus.MainActivity">
    
    
    
    <View
    
    android:id="@+id/status_bar"
    
    android:layout_width="match_parent"
    
    android:layout_height="0dp"
    
    android:background="@android:color/holo_red_light" />
    
    
    
    <LinearLayout
    
    android:layout_width="match_parent"
    
    android:layout_height="match_parent"
    
    android:layout_below="@id/status_bar"
    
    android:orientation="vertical">
    
    
    
    <TextView
    
    android:layout_width="wrap_content"
    
    android:layout_height="wrap_content"
    
    android:text="根布局为RelativeLayout时设置status_bar背景" />
    
    <Button
    
    android:onClick="changeColor"
    
    android:layout_width="wrap_content"
    
    android:layout_height="wrap_content"
    
    android:text="修改status_bar颜色" />
    
    <Button
    
    android:onClick="goLinerLayout"
    
    android:layout_width="wrap_content"
    
    android:layout_height="wrap_content"
    
    android:text="跳转LinearLayout根布局" />
    
    <Button
    
    android:onClick="changeMode"
    
    android:layout_width="wrap_content"
    
    android:layout_height="wrap_content"
    
    android:textColor="@android:color/holo_blue_light"
    
    android:text="修改Mode" />
    
    </LinearLayout>
    
    
    
    </RelativeLayout>

    (2)工具类

    /**
    
    * 设置状态栏透明工具类
    
    * Created by baopengjian on 2017/4/7.
    
    */
    
    
    
    public class UtilsStyle {
    
    
    
    /**
    
    * 布局中必须有一个id为status_bar的view来设置状态栏背景
    
    * 必须要在 setContentView之后调用
    
    *  onCrete中,onContentChange之前
    
    * @param activity 当前页面
    
    */
    
    public static void setTranslateStatusBar(Activity activity) {
    
        // 4.4以上处理
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // android
        
                   activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        // 状态栏透明
    
            View status_bar = activity.findViewById(R.id.status_bar);// 标题栏id
    
            if (status_bar != null) {
        
                ViewGroup.LayoutParams params = status_bar.getLayoutParams();
            
                params.height = getStatusBarHeight(activity);
    
                status_bar.setLayoutParams(params);
        
            }
    
        }
    
        //5.0 以上处理
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
            Window window = activity.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);
    
        }
    
    }
    
    
    
    
    
    private 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;
    
    }
    
    
    
    /**
    
    * Flag只有在使用了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
    
    * 并且没有使用 FLAG_TRANSLUCENT_STATUS的时候才有效,也就是只有在状态栏全透明的时候才有效。
    
    * @param activity
    
    * @param bDark
    
    */
    
    public static void setStatusBarMode(Activity activity, boolean bDark) {
    
        //6.0以上
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
            View decorView = activity.getWindow().getDecorView();
    
            if (decorView != null) {
    
                int vis = decorView.getSystemUiVisibility();
    
                if (bDark) {
    
                    vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
    
                } else {
    
                    vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
    
                }
    
                decorView.setSystemUiVisibility(vis);
    
            }
    
        }
    
        }
    
    }

    (3)使用

    public class MainActivity extends AppCompatActivity {
    
    
    
    private boolean isRed = true;
    
    private boolean isDarkMode = true;
    
    @Override
    
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.activity_main);
    
        //注意使用位置在setContentView后,onContentChange之前
        UtilsStyle.setTranslateStatusBar(this);
    
    }
    
    
    
    public void changeColor(View v){
    
    View status_bar = findViewById(R.id.status_bar);
    
    if(isRed){
    
    status_bar.setBackgroundResource(android.R.color.holo_blue_light);
    
    }else{
    
    status_bar.setBackgroundResource(android.R.color.holo_red_light);
    
    }
    
    isRed = !isRed;
    
    }
    
    
    
    public void goLinerLayout(View v){
    
    startActivity(new Intent(MainActivity.this,LinearRootActivity.class));
    
    }
    
    
    
    public void changeMode(View v){
    
    UtilsStyle.setStatusBarMode(this,!isDarkMode);
    
    isDarkMode = !isDarkMode;
    
    }
    
    }
    
    
    
    
    
    

     

    展开全文
  • Android沉浸式状态栏(透明状态栏)最佳实现

    万次阅读 多人点赞 2016-12-06 16:58:39
    Android沉浸式状态栏(透明状态栏)最佳实现 在Android4.4之前,我们的应用没法改变手机的状态栏颜色,当我们打开应用时,会出现上图中左侧的画面,在屏幕的顶部有一条黑色的状态栏,和应用的风格非常不协调;为了...
  • Android 沉浸式状态栏状态栏一体化、透明状态栏、仿iOS透明状态栏  http://blog.csdn.net/jdsjlzx/article/details/50437779 注:状态栏的字体颜色位白色, 如果状态栏背景为白色,上面的博客已经解决了。...
  • 1.实现透明状态栏 安卓4.4以上才可以实现透明状态栏,具体代码如下: Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 实现透明状态栏会默认把应用的...
  • 看了网上介绍,关于沉浸式状态栏大概有几种,透明状态栏,变色状态栏,沉浸式状态栏。变色状态栏大概只是通用说法,无论沉浸式还是透明的 都可以实现状态栏的变色。这里就不再介绍。 1,透明状态栏顾名思义就是透明...
  • Android布局顶到状态栏or状态栏布局or沉浸式状态栏1.状态栏里面开始布局的设置主题&lt;style name="NoActionBar" parent="Theme.AppCompat.Light.DarkActionBar"&gt; &lt;item ...
  • 这是一个为Android App 设置状态栏的工具类, 可以在4.4及其以上系统中实现 沉浸式状态栏/状态栏变色,支持设置状态栏透明度,满足你司设计师的各种要求(雾)。 本着不重复造轮子的原则,在网上找到了一个工具类,...
  • 今天突然出现的问题,在状态栏左下角的搜索框搜索OneNote没有任何反应,对,就是这个地方。 最后在另一篇博客上找到了答案,那篇博客也是在知乎找到的答案,虽然是用被人的方法解决了问题,但我还是打算记下来; 1...
  • Android 去掉状态栏 去掉标题栏 沉浸式状态栏 状态栏重叠 布局重叠 SystemBarTintManager systembartint-1.0.4
  • 这个库的地址贴一遍: ...1.四种效果,自定义颜色的状态栏和导航栏,半透明状态栏和导航栏, 沉浸式状态栏和导航栏,隐藏状态栏和导航栏; 2.可以自定义状态栏和导航栏的颜色和透明度; 3.KITKAT(A
  • 2.状态栏为背景图片效果 状态栏为图片效果.jpg 3.侧滑页面效果 侧滑页面效果.jpg 4.自定义渐变效果 自定义渐变效果.jpg 5.含ActionBar效果 含ActionBar效果.jpg 工具类 package 包名; import ...
  • 这是一个为Android App 设置状态栏的工具类, 可以在4.4及其以上系统中实现 沉浸式状态栏/状态栏变色,支持设置状态栏透明度,满足你司设计师的各种要求(雾)。 在此之前我写过一篇Android App 沉浸式状态栏解决方案...
  • 透明状态栏(沉浸式状态栏

    千次阅读 2016-01-25 23:23:07
    透明状态栏(沉浸式状态栏)透明状态栏(Translucate StatusBar)是android从4.4开始模仿ios推出的一种模式,他可以改变状态栏的颜色,使其更加的与自己的app样式所统一android 4.4推出的状态栏为透明样式,但会有一...
  • iOS 更改状态栏颜色和隐藏状态栏

    千次阅读 2018-09-11 15:39:58
    更改状态栏颜色 iOS7以后 状态栏的字体为黑色:UIStatusBarStyleDefault 状态栏的字体为白色:UIStatusBarStyleLightContent 解决方案 1、在info.plist中,将View controller-based status bar appearance 设为...
  • Android状态栏着色-透明状态栏

    千次阅读 2016-11-10 11:34:28
    最近项目上有需求 ,要求状态栏透明化 。还有需求是拖动状态栏标题一下的内容,标题栏的颜色要变化 。这里所谓的既是状态栏着色,也是我们经常听到的沉浸式状态栏,关于沉浸式的称呼网上也有很多吐槽的,这里就不做...
  • 做应用有时候我们需要界面是全屏显示的,也就是没有状态栏的,或者说修改状态栏的背景颜色,让整个屏幕的风格和界面保持一致的(沉浸式?),几行代码轻松搞定! 1、隐藏状态栏 在onCreate方法里面添加页面状态 ...
  • 1.设置状态栏透明方法 public static void makeStatusBarTransparent(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } Window windo...
  • android状态栏一体化(沉浸式状态栏)

    千次阅读 2016-07-27 14:04:56
    Android 沉浸式状态栏状态栏一体化、透明状态栏、仿ios透明状态栏 http://blog.csdn.net/jdsjlzx/article/details/50437779注:状态栏的字体颜色位白色, 如果状态栏背景为白色,上面的博客已经解决了。...
  • 这是一个为Android App 设置状态栏的工具类, 可以在4.4及其以上系统中实现 沉浸式状态栏/状态栏变色,支持设置状态栏透明度,满足你司设计师的各种要求(雾)。 在此之前我写过一篇Android App 沉浸式状态栏...
  • 版本要求 沉浸式状态栏效果是在android 4.4的时候出现...2.修改状态栏颜色为透明色,将标题栏扩展到状态栏下面,以达到沉浸式效果 需要注意的坑 1.需要注意的是状态栏的字体颜色  目前可实现沉浸式效果的状态栏...
  • 通过主题设置状态栏 在API21(android 5.0)之后,设置状态栏透明效果为半透明,并且为了保证在API19(android 4.4)之前的正常使用,所以需要3份不同的style文件。即values-v19(android 4.4之前使用),values-...
  • 开发 App 的时候,常常需要做出沉浸式状态栏的效果。 在 iOS 平台,默认就是沉浸式的,View 的内容会从屏幕顶部开始绘制,若不进行处理,就会被状态栏覆盖。因此可以手动获取状态栏的高度,用样式留出状态栏的空间,...
  • 沉浸式状态栏究其根本就是将布局内容延伸到状态栏中,让状态栏覆盖在布局上或者隐藏。 实现 首先,要修改状态栏android版本至少要在4.4以上,并且在4.4是不能让状态栏透明的,只能达到一种半透明的阴影背景,而在5.x...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,401
精华内容 14,560
关键字:

状态栏