该系列文章总纲链接:专题分纲目录 Android SystemUI组件
本章关键点总结 & 说明:
说明:本章节持续迭代之前章节的思维导图,主要关注左侧SystemBars分析中导航栏部分即可。
1 导航栏创建之makeStatusBarView
通过上一篇文章的分析,我们知道 addNavigationBar是在addStatusBarWindow之后执行的,addStatusBarWindow代码实现如下:
private void addStatusBarWindow() {
makeStatusBarView();//创建statusbar视图
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
addStatusBarWindow中makeStatusBarView也执行了导航栏相关逻辑,相关代码如下:
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
//...
try {
//关键点1:导航栏显示与否
boolean showNav = mWindowManagerService.hasNavigationBar();
//是否显示导航栏
if (showNav) {
//关键点2:加载导航栏布局
mNavigationBarView =
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
mNavigationBarView.setDisabledFlags(mDisabled);
mNavigationBarView.setBar(this);
mNavigationBarView.setOnVerticalChangedListener(
new NavigationBarView.OnVerticalChangedListener() {
@Override
public void onVerticalChanged(boolean isVertical) {
if (mSearchPanelView != null) {
mSearchPanelView.setHorizontal(isVertical);
}
mNotificationPanel.setQsScrimEnabled(!isVertical);
}
});
//设置导航栏触摸事件
mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event);
return false;
}});
}
} catch (RemoteException ex) {
// no window manager? good luck with that
}
//...
startGlyphRasterizeHack();
return mStatusBarView;
}
这里主要分析两个部分:navigationBar显示与否 和 导航栏Layout相关。
1.1 navigationBar显示与否
导航栏显示与否关键在于方法mWindowManagerService.hasNavigationBar的实现,这里最终是掉用到了PhoneWindowManager中的hasNavigationBar方法。代码如下所示:
public class PhoneWindowManager implements WindowManagerPolicy {
//...
public boolean hasNavigationBar() {
return mHasNavigationBar;
}
//...
}
这里变量mHasNavigationBar的赋值操作为:
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
这里可以看到 导航栏的配置主要是在/res/res/values中名为config_showNavigationBar的标识,即为默认的配置,如下所示:
<!-- 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>
因此,这里可以根据需求修改该配置。
1.2 导航栏Layout相关
加载导航栏布局的语句为:
NavigationBarView = (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
从布局文件(res\layout\navigation_bar.xml)中来来看,xml文件内容如下:
<com.android.systemui.statusbar.phone.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@drawable/system_bar_background"
>
<!--横向导航栏-->
<FrameLayout android:id="@+id/rot0"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false"
android:id="@+id/nav_buttons"
android:animateLayoutChanges="true"
>
<!-- navigation controls -->
<View
android:layout_width="@dimen/navigation_side_padding"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible"
/>
<!--back按钮-->
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
android:layout_weight="0"
android:scaleType="center"
android:contentDescription="@string/accessibility_back"
/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<!--home按钮-->
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
android:layout_width="@dimen/navig