我们使用的大多数android手机上的Home键,返回键以及menu键都是实体触摸感应按键。如果你用Google的Nexus4或Nexus5话,你会发现它们并没有实体按键或触摸感应按键,取而代之的是在屏幕的下方加了一个小黑条,在这个黑条上有3个按钮控件,这种设置无疑使得手机的外观的设计更加简约。但我遇到身边用Nexus 4手机的人都吐槽这种设计,原因很简单:好端端的屏幕,被划出一块区域用来显示3个按钮(如下图所示):Back, Home, Recent。并且它一直用在那里占用着。
在android源码中,那一块区域被叫做NavigationBar。同时,google在代码中也预留了标志,用来控制它的显示与隐藏。NavigationBar的显示与隐藏的控制是放在SystemU中的,具体的路径是:frameworksbasepackagesSystemUI。对android4.0以上的手机而言,SystemUi包含两部分:StatusBar和NavigationBar。在SystemUI的工程下有一个类PhoneStatusBar.java,在该类中可以发现关于控制NavigationBar的相关代码:
在start()方法里可以看到NavigationBar是在那时候被添加进来,但只是添加,决定它显示还是隐藏是在后面控制的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<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()具体的实现方法如下:
1
2
3
4
5
6
7<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>
1
2
3
4
5
6
7
8
9
10
11
12<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()接口,
1
2
3
4<span style="font-size:18px;"> @Override public boolean hasNavigationBar() { return mPolicy.hasNavigationBar(); }</span>
Policy向下调用实际上调用的是PhoneWindowManager实现的hasNavigationBar方法,下面代码是PhoneWindowManager中的hasNavigationBar()方法。
1
2
3
4
5<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)方法中找到,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<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>
1.首先从系统的资源文件中取设定值config_showNavigationBar, 这个值的设定的文件路径是frameworks/base/core/res/res/values/config.xml
1
2
3<!-- 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>
所以上面的两处设定共同决定了NavigationBar的显示与隐藏。
最后
以上就是干净大碗最近收集整理的关于如何控制android系统中NavigationBar 的显示与隐藏的全部内容,更多相关如何控制android系统中NavigationBar内容请搜索靠谱客的其他文章。
发表评论 取消回复