如何控制android系统中NavigationBar 的显示与隐藏
我们使用的大多数android手机上的Home键,返回键以及menu键都是实体触摸感应按键。如果你用Google的Nexus4或Nexus5话,你会发现它们并没有实体按键或触摸感应按键,取而代之的是在屏幕的下方加了一个小黑条,在这个黑条上有3个按钮控件,这种设置无疑使得手机的外观的设计更加简约。但我遇到身边用Nexus 4手机的人都吐槽这种设计,原因很简单:好端端的屏幕,被划出一块区域用来显示3个按钮(如下图所示):Back, Home, Recent。并且它一直用在那里占用着。
在android源码中,那一块区域被叫做NavigationBar。同时,google在代码中也预留了标志,用来控制它的显示与隐藏。NavigationBar的显示与隐藏的控制是放在SystemU中的,具体的路径是:\frameworks\base\packages\SystemUI。对android4.0以上的手机而言,SystemUi包含两部分:StatusBar和NavigationBar。在SystemUI的工程下有一个类PhoneStatusBar.java,在该类中可以发现关于控制NavigationBar的相关代码:
在start()方法里可以看到NavigationBar是在那时候被添加进来,但只是添加,决定它显示还是隐藏是在后面控制的。
- <span style="font-size:18px;">@Override
- public void start() {
- mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay();
- updateDisplaySize();
- /// M: Support Smartbook Feature.
- if (SIMHelper.isMediatekSmartBookSupport()) {
- /// M: [ALPS01097705] Query the plug-in state as soon as possible.
- mIsDisplayDevice = SIMHelper.isSmartBookPluggedIn(mContext);
- Log.v(TAG, "start, mIsDisplayDevice=" + mIsDisplayDevice);
- }
- super.start(); // calls createAndAddWindows()
- addNavigationBar();
- // Lastly, call to the icon policy to install/update all the icons.
- mIconPolicy = new PhoneStatusBarPolicy(mContext);
- mHeadsUpObserver.onChange(true); // set up
- if (ENABLE_HEADS_UP) {
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(SETTING_HEADS_UP), true,
- mHeadsUpObserver);
- }
- }</span>
其中的addNavigationBar()具体的实现方法如下:
- <span style="font-size:18px;"> // For small-screen devices (read: phones) that lack hardware navigation buttons
- private void addNavigationBar() {
- if (DEBUG) Slog.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
- if (mNavigationBarView == null) return;
- prepareNavigationBarView();
- mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
- }</span>
可以看到Navigationbar实际上windowmanager向window窗口里添加一个view。在调用addNavigationBar()方法之前会回调start()的父方法super.start()来判断是否要添加NavigationBar。在super.start()的调用父类方法里会调用createAndAddWindows(),该方法内会判断是否需要添加显示NavigationBar,然后决定是否要实例化NavigationBarView.
- <span style="font-size:18px;">try {
- boolean showNav = mWindowManagerService.hasNavigationBar();
- if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
- if (showNav) {
- mNavigationBarView =
- (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
- mNavigationBarView.setDisabledFlags(mDisabled);
- mNavigationBarView.setBar(this);
- }
- } catch (RemoteException ex) {
- // no window manager? good luck with that
- }</span>
WindowManagerService类实现了WindowManagerPolicy的接口,所以WindowManagerService会回调WindowManagerPolicy 的hasNavigationBar()接口,
- <span style="font-size:18px;"> @Override
- public boolean hasNavigationBar() {
- return mPolicy.hasNavigationBar();
- }</span>
Policy向下调用实际上调用的是PhoneWindowManager实现的hasNavigationBar方法,下面代码是PhoneWindowManager中的hasNavigationBar()方法。
- <span style="font-size:18px;">// Use this instead of checking config_showNavigationBar so that it can be consistently
- // overridden by qemu.hw.mainkeys in the emulator.
- public boolean hasNavigationBar() {
- return mHasNavigationBar;
- }</span>
而mHasNavigationBar的赋值可以在PhoneWindowManager中的setInitialDisplaySize(Display display, int width, int height, int density)方法中找到,
- <span style="font-size:18px;"> if (!mHasSystemNavBar) {
- mHasNavigationBar = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_showNavigationBar);
- // Allow a system property to override this. Used by the emulator.
- // See also hasNavigationBar().
- String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
- if (! "".equals(navBarOverride)) {
- if (navBarOverride.equals("1")) mHasNavigationBar = false;
- else if (navBarOverride.equals("0")) mHasNavigationBar = true;
- }
- } else {
- mHasNavigationBar = false;
- }</span>
从上面代码可以看到mHasNavigationBar的值的设定是由两处决定的:
1.首先从系统的资源文件中取设定值config_showNavigationBar, 这个值的设定的文件路径是frameworks/base/core/res/res/values/config.xml
- <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
- autodetected from the Configuration. -->
- <bool name="config_showNavigationBar">false</bool>
2.然后系统要获取“qemu.hw.mainkeys”的值,这个值可能会覆盖上面获取到的mHasNavigationBar的值。如果“qemu.hw.mainkeys”获取的值不为空的话,不管值是true还是false,都要依据后面的情况来设定。
所以上面的两处设定共同决定了NavigationBar的显示与隐藏。
如何控制android系统中NavigationBar 的显示与隐藏的更多相关文章
- 控制input输入框中提示信息的显示和隐藏的方法
在运用html+css+javascrpt进行页面制作时,我们往往会遇到一些影响用户体验,而又容易被我们忽视的小细节.比如,input输入框中的提示信息,怎样才能根据对象获得和失去焦点而实现其显示和隐 ...
- Android系统中设置TextView的行间距(非行高)
Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...
- Android系统中的广播(Broadcast)机制简要介绍和学习计划
在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个 ...
- Android系统中 setprop,getprop,watchprops命令的使用
如:在frameworks/opt/net/ims/src/java/com/android/ims/ImsManager.java if (SystemProperties.get("pe ...
- 用adb pull命令从android系统中读取文件失败的原因及解决办法
问题:使用adb pull命令从android系统中读取文件失败.显示:Permission denied 原因:是由于文件权限原因引起. 使用ls -l命令查看android系统中的 ...
- Android系统中setprop,getprop,watchprops命令的使用(转载)
转自:http://blog.csdn.net/yao_guet/article/details/6531241 在android系统中,有一些初始化的配置文件,例如: /init.rc /defau ...
- 在Android系统中修改Android.mk使其同时编译rgb2565和rgb2888(向out/host/linux-x86/bin/下新增加一个工具命令)【转】
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7514559 在Android系统中修改android.mk使其同时编译rgb2565和rgb ...
- AIDL在android系统中的作用
AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.最近看了下AIDL在A ...
- Android系统中的6种模式
Android系统中的6种模式 1:一般启动模式(normal mode): 功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode): 此模式和正常启动一样 ...
随机推荐
- DOpus 10.5 使用帮助
在线手册 http://www.dearopus.com/ http://resource.dopus.com/ http://www.gpsoft.com.au/help/opus10/ 应急截图编 ...
- PHPUnit单元测试
单元测试 PHPUnit <?php /** * 定义一个用来被测试的类RemoteConnect * @author json * */ class RemoteConnect{ public ...
- Springboot项目启动报错,提示Cannot determine embedded database driver class for database type NONE
我在springboot项目里面引入了数据库的配置: <dependency> <groupId>org.mybatis.spring.boot</groupId> ...
- Unity3D 导入Xcode 工程后。编译很慢
Unity3D 导入Xcode 工程后.编译很慢 选择Targets-->Build options -->debug information format 然后选择DWARF 这样再次 ...
- Apache Kafka学习 (一)
前言:最近公司开始要研究大数据的消息记录,于是开始研究kafka. 市面上kafka的书很少,有的也版本比较落后,于是仗着自己英文还不错,上官网直接学习. ^_^ 1. 开始 - 基本概念 学习一样东 ...
- git ingore添加忽略文件无较的解决方法
一.启动Git Bash并切换到项目目录下 二.执行下列语句: git rm -r --cached . git add . git commit -m 'update .gitignore' 三.O ...
- logback debug 日志没有信息
可能是项目绑定的日志不是logback的jar包,而是其他包,具体可查看tomcat启动日志 log4j:WARN No appenders could be found for logger (or ...
- 解决mybatis报错Result Maps collection does not contain value for java.lang.Integer
解决办法:1.检查mybatis的xml配置 2.在某处肯定有配错了的,如"resultMap" -->"resultType" [html] view ...
- Mac下Android绘制点9格式png以及解决IllegalArgumentException: Unknown image type 0报错
在Mac下的AndroidStudio中,右键png图片选择“create 9-patch-file”时会报错:IllegalArgumentException: Unknown image type ...
- Python学习笔记三:模块
一:模块 一个模块就是一个py文件,里面定义了一些业务函数.引用模块,可以用import语句导入.导入模块后,通过 模块.函数名(参数) 来使用模块中的函数.如果存在多个同名模块,则前面模块名需要加 ...