-
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>
这样我们就实现类似于海岛奇兵和爱奇艺的沉浸式模式效果了,如下图所示。
可以看到,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态。
这就是最标准的沉浸式模式。
关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。
微信扫一扫下方二维码即可关注:
-
android沉浸式状态栏、变色状态栏、透明状态栏、修改状态栏颜色及透明
2016-03-28 15:56:49实现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,先声明一下:本篇博客效果下图:
关于这个状态栏变色到底叫「Immersive Mode」/「Translucent Bars」有兴趣可以去 为什么在国内会有很多用户把 「透明栏」(Translucent Bars)称作 「沉浸式顶栏」?上面了解了解,请勿指点我说的博文标题起得不对,thx。
恩,接下来正题。
首先只有大于等于4.4版本支持这个半透明状态栏的效果,但是4.4和5.0的显示效果有一定的差异,所有本篇博文内容为:
- 如何实现半透明状态栏效果在大于4.4版本之上。
- 如何让4.4的效果与5.0的效果尽可能一致。
看了不少参考文章,都介绍到这个库,大家可以了解:SystemBarTint。
不过本篇博文并未基于此库,自己想了个hack,对于此库源码有空再看了。
二、效果图
先贴下效果图,以便和实现过程中做下对比
- 4.4 模拟器
- 5.x 真机
[new]贴个如果顶部是图片的效果图,其实是一样的,为了方便我就放侧栏的顶部了。
稍等,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就会有挤一块的感觉了,类似会这样:
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的效果图是:
其实还不错,有个渐变的效果。
现在5.x的效果:
可以看到5.x默认并非是一个渐变的效果,类似是一个深一点的颜色。
在看看我们md的规范
状态栏应该是一个比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 模拟器
- 5.x 真机
ok,这样就结束啦~~
源码地址:https://github.com/hongyangAndroid/ColorfulStatusBar
欢迎关注我的微博:
http://weibo.com/u/3165018720群号:463081660,欢迎入群
微信公众号:hongyangAndroid
(欢迎关注,第一时间推送博文信息)参考
- http://blog.raffaeu.com/archive/2015/04/11/android-and-the-transparent-status-bar.aspx
- https://mindofaandroiddev.wordpress.com/2013/12/28/making-the-status-bar-and-navigation-bar-transparent-with-a-listview-on-android-4-4-kitkat/
- http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1117/1992.html
- http://developer.android.com/intl/zh-cn/reference/android/view/View.html#attr_android:fitsSystemWindows
-
状态栏总结(沉浸式状态栏+状态栏颜色+状态栏字体的颜色)
2018-12-12 22:37:17今天总结一下状态栏的使用,当然也是参考别人的。但是总归自己得试试,然后把常用的几种情况记下来,因为这些东西是死的,下次拿过来就可以用。 一. 沉浸式状态栏 :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 使用的沉浸式较多一些:透明状态栏+黑色 或者透明状态栏+白色
业务模块中: 可以统一设置状态栏颜色,以及字体颜色。
-
51_Android设置状态栏透明与设置状态栏字体颜色Mode
2017-04-07 11:31:05沉浸式状态栏:,状态栏隐藏,在手指做了相关操作后,状态栏显示出来,例如视频播放器,在播放视频时是隐藏状态栏的,但是点击屏幕的时候,状态栏会显示出来,再例如文本阅读器,在阅读的时候是全屏的,然后从屏幕...@[toc]
#1 概念:
变色状态栏(透明状态栏):指的是状态栏与导航栏颜色相同,或者透明
沉浸式状态栏:,状态栏隐藏,在手指做了相关操作后,状态栏显示出来,例如视频播放器,在播放视频时是隐藏状态栏的,但是点击屏幕的时候,状态栏会显示出来,再例如文本阅读器,在阅读的时候是全屏的,然后从屏幕上方下滑或者下方上划,虚拟键和状态栏出现了,但却是直接覆盖在程序文字上的,这是所谓的沉浸式状态栏。
#2 效果图
(1)透明效果:
a. android 4.4以下不起作用(注意兼容):
b. 4.4和5.0以上(5.0以上要调用另外的标记重新设置Flag,不然状态栏会有灰色的透明阴影效果)
(2)修改状态栏字体颜色(6.0以下不起效果,不能直接设置,而是通过两种模式,魅族、小米有对应暴露方法,但本文得考虑所有机型)
修改之后:
#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:39Android沉浸式状态栏(透明状态栏)最佳实现 在Android4.4之前,我们的应用没法改变手机的状态栏颜色,当我们打开应用时,会出现上图中左侧的画面,在屏幕的顶部有一条黑色的状态栏,和应用的风格非常不协调;为了... -
Android 沉浸式状态栏、状态栏一体化、透明状态栏、仿iOS透明状态栏
2016-06-14 09:53:23Android 沉浸式状态栏、状态栏一体化、透明状态栏、仿iOS透明状态栏 http://blog.csdn.net/jdsjlzx/article/details/50437779 注:状态栏的字体颜色位白色, 如果状态栏背景为白色,上面的博客已经解决了。... -
安卓状态栏优化,实现透明状态栏,沉侵式状态栏,改变状态栏颜色
2016-08-19 16:58:341.实现透明状态栏 安卓4.4以上才可以实现透明状态栏,具体代码如下: Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 实现透明状态栏会默认把应用的... -
Android 沉浸式状态栏以及 透明状态栏 和修改状态栏颜色
2016-09-15 20:20:31看了网上介绍,关于沉浸式状态栏大概有几种,透明状态栏,变色状态栏,沉浸式状态栏。变色状态栏大概只是通用说法,无论沉浸式还是透明的 都可以实现状态栏的变色。这里就不再介绍。 1,透明状态栏顾名思义就是透明... -
Android布局顶到状态栏or状态栏布局or沉浸式状态栏
2018-07-06 09:58:09Android布局顶到状态栏or状态栏布局or沉浸式状态栏1.状态栏里面开始布局的设置主题<style name="NoActionBar" parent="Theme.AppCompat.Light.DarkActionBar"> <item ... -
StatusBarUtil 状态栏工具类(实现沉浸式状态栏/变色状态栏)
2017-06-30 13:38:41这是一个为Android App 设置状态栏的工具类, 可以在4.4及其以上系统中实现 沉浸式状态栏/状态栏变色,支持设置状态栏透明度,满足你司设计师的各种要求(雾)。 本着不重复造轮子的原则,在网上找到了一个工具类,... -
解决win10状态栏的搜索框无法搜索本地应用或无反应
2018-08-16 15:40:20今天突然出现的问题,在状态栏左下角的搜索框搜索OneNote没有任何反应,对,就是这个地方。 最后在另一篇博客上找到了答案,那篇博客也是在知乎找到的答案,虽然是用被人的方法解决了问题,但我还是打算记下来; 1... -
Android 去掉状态栏 去掉标题栏 沉浸式状态栏 状态栏重叠 布局重叠 SystemBarTintManager systembartint-...
2015-12-30 11:52:05Android 去掉状态栏 去掉标题栏 沉浸式状态栏 状态栏重叠 布局重叠 SystemBarTintManager systembartint-1.0.4 -
透明状态栏导航栏、沉浸式状态栏导航栏的终极解决方案
2017-08-24 14:56:26这个库的地址贴一遍: ...1.四种效果,自定义颜色的状态栏和导航栏,半透明状态栏和导航栏, 沉浸式状态栏和导航栏,隐藏状态栏和导航栏; 2.可以自定义状态栏和导航栏的颜色和透明度; 3.KITKAT(A -
Android沉浸式状态栏/状态栏设置背景图片/自定义渐变式状态栏
2019-08-23 15:48:212.状态栏为背景图片效果 状态栏为图片效果.jpg 3.侧滑页面效果 侧滑页面效果.jpg 4.自定义渐变效果 自定义渐变效果.jpg 5.含ActionBar效果 含ActionBar效果.jpg 工具类 package 包名; import ... -
Android 状态栏工具类(实现沉浸式状态栏/变色状态栏)
2016-06-06 09:44:39这是一个为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最近项目上有需求 ,要求状态栏透明化 。还有需求是拖动状态栏标题一下的内容,标题栏的颜色要变化 。这里所谓的既是状态栏着色,也是我们经常听到的沉浸式状态栏,关于沉浸式的称呼网上也有很多吐槽的,这里就不做... -
android 隐藏状态栏和修改状态栏的背景颜色(沉浸式状态栏)
2017-07-06 18:09:12做应用有时候我们需要界面是全屏显示的,也就是没有状态栏的,或者说修改状态栏的背景颜色,让整个屏幕的风格和界面保持一致的(沉浸式?),几行代码轻松搞定! 1、隐藏状态栏 在onCreate方法里面添加页面状态 ... -
Android 设置状态栏透明和状态栏文字自适应
2020-04-27 18:46:341.设置状态栏透明方法 public static void makeStatusBarTransparent(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } Window windo... -
android状态栏一体化(沉浸式状态栏)
2016-07-27 14:04:56Android 沉浸式状态栏、状态栏一体化、透明状态栏、仿ios透明状态栏 http://blog.csdn.net/jdsjlzx/article/details/50437779注:状态栏的字体颜色位白色, 如果状态栏背景为白色,上面的博客已经解决了。... -
Android 状态栏工具类(实现沉浸式状态栏 / 变色状态栏)
2016-04-19 21:40:27这是一个为Android App 设置状态栏的工具类, 可以在4.4及其以上系统中实现 沉浸式状态栏/状态栏变色,支持设置状态栏透明度,满足你司设计师的各种要求(雾)。 在此之前我写过一篇Android App 沉浸式状态栏... -
android沉浸式状态栏以及状态栏颜色更改
2018-08-20 10:46:50版本要求 沉浸式状态栏效果是在android 4.4的时候出现...2.修改状态栏颜色为透明色,将标题栏扩展到状态栏下面,以达到沉浸式效果 需要注意的坑 1.需要注意的是状态栏的字体颜色 目前可实现沉浸式效果的状态栏... -
android状态栏(沉浸式状态栏,改变状态栏字体颜色,背景颜色)
2018-12-03 22:12:01通过主题设置状态栏 在API21(android 5.0)之后,设置状态栏透明效果为半透明,并且为了保证在API19(android 4.4)之前的正常使用,所以需要3份不同的style文件。即values-v19(android 4.4之前使用),values-... -
React Native 获取状态栏高度,实现沉浸式状态栏
2019-06-04 02:07:04开发 App 的时候,常常需要做出沉浸式状态栏的效果。 在 iOS 平台,默认就是沉浸式的,View 的内容会从屏幕顶部开始绘制,若不进行处理,就会被状态栏覆盖。因此可以手动获取状态栏的高度,用样式留出状态栏的空间,... -
Android 透明状态栏及设置状态栏字体颜色
2018-09-21 17:16:32沉浸式状态栏究其根本就是将布局内容延伸到状态栏中,让状态栏覆盖在布局上或者隐藏。 实现 首先,要修改状态栏android版本至少要在4.4以上,并且在4.4是不能让状态栏透明的,只能达到一种半透明的阴影背景,而在5.x...
-
JAVAEE主流框架之SpringMvc框架实战开发教程(源码+讲义
-
Qt项目实战之基于Redis的网络聊天室
-
250B石英晶体测试参数详解.doc
-
性能测试面面观
-
MFC开发简单聊天程序
-
输入车牌号码时弹出的键盘.zip
-
2021.1.25-day5 列表作业
-
复核系统总结
-
Selenium3分布式与虚拟化
-
Oracle Database 21c New Features 十大新特性
-
JavaEE框架(Maven+SSM)全程实战开发教程(源码+讲义)
-
redis的安装部署.docx
-
redis-6.0.10.sh
-
家用电器远程控制系统的设计
-
Java list集合排序
-
金属薄膜的缺陷模对一维光子晶体滤波特性的影响
-
算法导论(基础知识)——编程大牛的必经之路
-
基于并行深度残差网络的堆场烟雾检测方法
-
面向激光追踪测量系统二维回转轴系的误差分析及精度保证
-
基于二维小波变换的图像除雾技术