与Status Bar和Navigation Bar相关的一些东西
与StatusBar和NavigationBar相关的东西有两种,一是控制它们的显示与隐藏,二是控制它们的透明与否及背景。
在2.3及以前,StatusBar只能显示与隐藏,即全屏模式,通过WindowManager.LayoutParams.FLAG_FULLSCREEN
来实现:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
并可通过以下Flag使Activity的布局可以使用整个屏幕,状态栏会显示到Activity上方并遮盖部分布局
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
在3.0(API 11)中,添加了一个重要的方法:setSystemUiVisibility(int)
,用于控制包括Status Bar在内的一些窗口装饰元素的显示,并添加了View.STATUS_BAR_VISIBLE
和View.STATUS_BAR_HIDDEN
两个Flag用于控制Status Bar的显示与隐藏,但在4.0(API 14)中废弃了。
在4.0(API 14)中,Andorid引入了Navigation Bar,并添加了一个Flag:SYSTEM_UI_FLAG_HIDDEN_NAVIGATION
用于控制Navigatoin Bar的显示。3.0中被弃用的View.STATUS_BAR_VISIBLE
被View.SYSTEM_UI_VISIBLE
替代,View.STATUS_BAR_HIDDEN
被View.SYSTEM_UI_LOW_PROFILE
替代,View.SYSTEM_UI_LOW_PROFILE
不会使Status Bar和Navigation Bar消失,而是会使它们变暗,降低它们对视觉的干扰,使用户可以专注于应用的内容,但仍可响应用户的交互,当和它们的交互发生时,会退出Low Profile的状态。
在4.1(API 16)中,对Status Bar和Navigation Bar的控制进一步增强,引入了View.SYSTEM_UI_FLAG_FULLSCREEN
,和View.SYSTEM_UI_HIDDEN_NAVIGATION
分别控制Status Bar和Navigation Bar的显示。并同时引入了另外三个Flag:View.SYSTEM_UI_FLAG_LAYOUT_STABLE
、View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
。
显示System UI:
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
隐藏System UI
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
通过上面那段View.SYSTEM_UI_FLAG_FULLSCREEN
、View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
相关的代码实现的全屏模式,可以隐藏掉Status Bar和Navigation Bar,但是这些都是很重要的功能,尤其是Navigation Bar,对于只有虚拟按键的手机,如果隐藏掉Navigation Bar,连切换程序都做不到,所以,当用户和手机有任何交互的时候都会重新显示Status Bar和Navigation Bar,这被称为LEAN BACK模式。这很适合视频播放的场景,但对于其他一些场景可能就不适合了,比如读书。
所以,在4.4(API 19)中引入了沉浸模式View.SYSTEM_UI_FLAG_IMMERSIVE
和View.SYSTEM_UI_FLAG_IMMERSIVE_STICK
。在IMMERSIVE模式中,用户的普通交互并不会使系统退出IMMERSIVE模式,如果要退出IMMERSIVE模式,需要在屏幕的顶部或底部向内滑动。这可以使用户专注于内容,但退出方式并不像LEAN BACK模式那么明显,所以在第一次进入IMMERSIVE时,系统会弹出一个UI提醒退出的方法。SYSTEM_UI_FLAG_IMMERSIVE
等需要和SYSTEM_UI_FLAG_FULLSCREEN
、SYSTEM_UI_FLAG_HIDE_NAVIGATION
一起使用。
IMMERSIVE_STICKY和IMMERSIVE的区别是,在IMMERSIVE中,用户从屏幕顶部或底部向内滑动时会退出IMMERSIVE模式,需要手动控制再次进入IMMERSIVE模式,而在IMMERSIVE_STICKY模式中,同样的操作只会使系统以半透明方法显示System UI方便用户操作,并会在一段时间后自动隐藏,此时并不会引起onSystemUiVibilityChanged
的调用。
可以看到,关于全屏,关于System UI的控制,如果想有好的体验,还是有很多细节需要处理的,不过幸好,chrisbanes大神写了一个类来处理这些细节:https://gist.github.com/chrisbanes/73de18faffca571f7292
除了控制System UI的显示和隐藏外,还可以使它们变成透明的,在4.4(API 19)中还引入了WindowManager.LayoutParams.FLAG_TRANSUCENT_STATUS
和WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
用于控制System UI变透明,这两个Flag分别对应于windowTranslucentStatus
和windowTranslucentNavigation
两个attr,并同时提供了相应的Theme(这些Theme都没有ActionBar),当使用这两个Flag时,SYSTEM_UI_FLAG_LAYOUT_STABLE
、SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
会被自动添加。
当System UI变透明后,Activity的UI占据整个屏幕,System UI覆盖在Activity的UI上面,对于一般的应用,虽然System UI透明了,但会发现效果并没有那么好,因为ActionBar还是在Status Bar下面,Status Bar变为透明后会透出Activity的UI,一般情况下这部分UI和ActionBar放到一起并不是那么协调。可以设置窗口的背景和ActionBar的色调一致,但会引起OverDraw,并且如果指定的布局撑不满全屏呢?
我们知道,Activity顶部的布局是DecorView,而DecorView继承自FrameLayout,所以可以添加两个View到DecorView中,占据Status Bar和Navigation Bar的位置,并设置它们的背景使其与ActionBar相配,但这需要计算Status Bar和Navigation Bar的大小,并且需要判断Navigation Bar的位置(Bottom or Right)。正好,也有人做了这样的事:https://github.com/jgilfelt/SystemBarTint
无论是LEAN_BACK模式还是IMMERSIVE模式,都使用到了4.1中引入的三个Flag:SYSTEM_UI_FLAG_LAYOUT_STABLE
、SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
,它们的用处并不像SYSTEM_UI_FLAG_FULLSCREEN
那么明显,而且名称还很相似,要了解它们的用处,需要先了解一个内容边衬区的概念(ContentInset)及一个重要的函数View.fitSystemWindows
。
默认情况下,应用程序窗口在Status Bar下面,系统已经处理好了应用窗口的显示,我们不需要关心Inset和fitSystemWindow,但有一些情况就要我们自己处理了。
当使用了Translucent System UI或SYSTEM_UI_FLAG_FULLSCREEN等时,Activity的UI可以显示到System UI下面,System UI在显示时可能会盖住Activity的UI,所以可能需要处理这样的情况,这就需要知道System UI会占用的空间大小是多少,这个大小就是内容边初区(ContentInset),系统会通过fitSystemWindows(Rect)
来通知我们,我们可以通过这个方法调整我们的内容显示。
还有一个方法是View.setFitSystemWindows(boolean)
,用于设置是否使用系统默认的fitSystemWindows
实现。系统的默认实现会消耗掉内容边衬区空间的占用,算到View的Padding里面,并返回true,否则什么也不做返回false,当返回false时,会继续调用View Hierarchy中其他View的fitSystemWindows
,直到某一个View中返回true,调用顺序是深度优先。如果我们决定自己处理System UI的空间占用,可以重写VIew的fitSystemWIndows
并返回true,如果自己只是做些处理,仍想调用系统的默认实现,要记得调用super.fitSystemWindows
并返回false。
接下来就可以说SYSTEM_UI_FLAG_LAYOUT_STABLE
等的作用了。在使用View.SYSTEM_UI_FLAG_FULLSCREEN|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
时,Status Bar和Navigation Bar都会隐藏,Activity的UI占据整个屏幕,当System UI再次显示时,应用程序窗口会被Resize,为System UI腾出空间,这会引起屏幕的跳动,这三个Flag的作用就在于此,SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
要和SYSTEM_UI_FLAG_LAYOUT_STABLE
一起使用,用于控制当Status Bar或Navigation Bar显示或隐藏时,Activity的UI是否会被Resize,当使用这三个Flag时,Activity会占用整个屏幕空间,并通过fitSystemWindows
传入的Insets标明Insets的大小(对于SYSTEM_UI_FLAG_FULLSCREEN
会同时包含ActionBar的大小),我们可以根据这个Insets的大小调整内容的显示,如果给ContentView设置fitSystemWindows为true,会自动把Iinset转化为padding。
有几点需要注意的是:
- 当调用
fitSystemWindows
时是深度优先遍历 setSystemUiVibility
是View中定义的方法,所以我们可以用Activity布局中任意一个View控制System UI,只要这个View不是Gone状态,系统会组合所有可见View的设置,所以一般情况下会直接对DecorView进行设置。- 当切换程序时,系统会清除
SYSTEM_UI_FLAG_FULLSCREEN
等Flag,所以需要通过setSystemUiVisibilityListener
、onWindowFocudChanged
等方法控制应用的状态。 - 魅族MX2,Flyme 3.5系统,Android 4.4.4,Immersive模式无法退出,不过这个机型有实体按键,所以影响不大,无法从顶部下拉或底部滑动退出全屏,因为Flyme系统本身就支持在全屏时拉出状态栏或调出任务切换,系统设置中也可以关闭这个功能。
参考:https://www.youtube.com/watch?v=cBi8fjv90E4&feature=youtu.be
与Status Bar和Navigation Bar相关的一些东西的更多相关文章
- Status bar and navigation bar appear over my view's bounds in iOS 7
转自:http://stackoverflow.com/questions/17074365/status-bar-and-navigation-bar-appear-over-my-views-bo ...
- Navigation bar 的注意事项
Navigation bar 的注意事项 Bar button item 使用 button 作为 custom view,初始化 isEnabled 为 false,注意顺序 需要设置 bar bu ...
- Customizing Navigation Bar and Status Bar
Like many of you, I have been very busy upgrading my apps to make them fit for iOS 7. The latest ver ...
- [Android] 获取系统顶部状态栏(Status Bar)与底部导航栏(Navigation Bar)的高度
Android一些设备都有上下两条bar,我们可以获取这些bar的信息.下面放上获取高度的代码.代码注释和其他方法有空再放. 原文地址请保留http://www.cnblogs.com/rossone ...
- [工作积累] Android: Hide Navigation bar 隐藏导航条
https://developer.android.com/training/system-ui/navigation.html View decorView = getWindow().getDec ...
- Android hide Navigation bar
最近一个app需要隐藏Navigation bar导航栏. 参考文档 http://blog.csdn.net/zwlove5280/article/details/52823128 http://j ...
- IOS7 状态栏和 Navigation Bar重叠的问题解决
一 Status bar重叠问题: 方法一:隐藏Status bar 在plist里面增加2个变量 Status bar is initially hidden -> YES Vie ...
- 把 Navigation Bar 下面那条线删掉的最简单的办法! — By: 昉
系统默认的 Navigation Bar 下面一直有条线,翻尽了文档却没找到能把它弄走的相关接口,处女座的简直木法忍啊有木有!!!! 研究了一下navigationBar下的子视图,原来只需要几行代码 ...
- android隐藏底部虚拟键Navigation Bar实现全屏
隐藏底部虚拟键Navigation Bar实现全屏有两种情况 第一种:始终隐藏,触摸屏幕时也不出现 解决办法:同时设置以下两个参数 View.SYSTEM_UI_FLAG_HIDE_NAVIGATIO ...
随机推荐
- 使用Mod_JK链接Apache和Tomcat
There are many potential problems associated with the default configuration of mod_jk. Let's say it ...
- IOS asc码替换
-(void)click:(UIButton *)btn { NSString *testStr = @"学>与全等"; NSStringEncoding encoding2 ...
- linux 下查看系统资源和负载,以及性能监控
1,查看磁盘 df -h 2,查看内存大小 free free [-m|g]按MB,GB显示内存 vmstat 3,查看cpu cat /proc/cpuinfo 只看 ...
- 【Selenium】2.安装Selenium IDE和 FireBug
本文供学习交流之用,没有商业用途,没有盈利. 完全是我自己为督促自己学习而翻译的.翻译的不好,见谅.来源于:http://www.guru99.com/install-selenuim-ide.htm ...
- 夺命雷公狗-----React---9--map数据的遍历
比如我们要实现的是这种效果: 用这种方法来写,她只能写死在哪,没啥意思,所以我们定义一个数据,然后来测试下map方法对她遍历出来的数据 <!DOCTYPE html> <html l ...
- PHP 教程
PHP 教程 源地址 PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言. PHP 是免费的,并且使用非常广泛.同时,对于像微软 ASP 这样的竞争者来说,PHP 无疑是另一种高效率的选项. ...
- Failed to execute request because the App-Domain could not be created.
原错误信息: 服务器应用程序不可用 您试图在此 Web 服务器上访问的 Web 应用程序当前不可用.请点击 Web 浏览器中的“刷新”按钮重试您的请求. 管理员注意事项: 详述此特定请求失败原因的错误 ...
- transition、animation在macbook air上图片动画边缘抖动
示例: BUG描述: 最近同事一项目中,产品提出在macbook air上,列表图片放大效果边缘出现抖动现象.在retina屏上没有此问题. 调试过程: 1.单独把结构分离.确定是否由其他元素引起. ...
- 手机APP测试体系
- Writing Your Own jQuery Plugins
Setting Up <script src="js/jquery-1.9.1.min.js"></script> <script src=" ...