SystemUI之NavigationBar导航栏

  • 布局结构

navigation_bar_window.xml à navigation_bar.xml

[NavigationBarFrame [NavigationBarView [NavigationBarInflaterView ] ] ]

View结构图:

二、代码控制流程

2.1、NavigationBar创建及View添加

StatusBar.java:

        start() à createAndAddWindows(result) à makeStatusBarView(result) à createNavigationBar(result) à mNavigationBarController.createNavigationBars(……)
  1. protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
  2. createNavigationBar(result);
  3. ……
  4. inflateStatusBarWindow();
  5. }
  1. protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
  2. mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
  3. }

NavigationBarController.java:

               createNavigationBars(……) à createNavigationBar(……) à
navBar. createView (……)
 
  1. void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
  2. ……
  3. ……
  4. NavigationBar navBar = new NavigationBar(context,
  5. mWindowManager,
  6. ……
  7. mUserTracker);
  8. mNavigationBars.put(displayId, navBar);
  9. View navigationBarView = navBar.createView(savedState);
  10. ……
  11. }
NavigationBar.java(Contains logic for a navigation bar view):
  1. public View createView(Bundle savedState) {
  2. WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
  3. WindowManager.LayoutParams.MATCH_PARENT,
  4. WindowManager.LayoutParams.MATCH_PARENT,
  5. WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
  6. ……
  7. PixelFormat.TRANSLUCENT);
  8. lp.token = new Binder();
  9. ……
  10. lp.setTrustedOverlay();
  11. NavigationBarFrame frame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
  12. R.layout.navigation_bar_window, null);
  13. View barView = LayoutInflater.from(frame.getContext()).inflate(
  14. R.layout.navigation_bar, frame);
  15. barView.addOnAttachStateChangeListener(this);
  16. mNavigationBarView = barView.findViewById(R.id.navigation_bar_view);
  17. mContext.getSystemService(WindowManager.class).addView(frame, lp)
  18. mContentResolver.registerContentObserver(
  19. Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
  20. false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
  21. ……
  22. return barView;
  23. }

备注 : 导航栏的具体位置在框架DisplayPolicy中根据方向等因素确定:

services\core\java\com\android\server\wm\DisplayPolicy.java

  1. private int layoutNavigationBar(DisplayFrames displayFrames, Rect contentFrame) {
  2. ……
  3. final int rotation = displayFrames.mRotation;
  4. final int displayHeight = displayFrames.mDisplayHeight;
  5. final int displayWidth = displayFrames.mDisplayWidth;
  6. final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
  7. ……
  8. if (navBarPosition == NAV_BAR_BOTTOM) {
  9. navigationFrame.top = Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom)
  10. - getNavigationBarFrameHeight(rotation, uiMode);
  11. else if (navBarPosition == NAV_BAR_RIGHT) {
  12. // Landscape screen; nav bar goes to the right.
  13. navigationFrame.left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right)
  14. - getNavigationBarWidth(rotation, uiMode);
  15. else if (navBarPosition == NAV_BAR_LEFT) {
  16. // Seascape screen; nav bar goes to the left.
  17. navigationFrame.right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left)
  18. + getNavigationBarWidth(rotation, uiMode);
  19. }
  20. ……
  21. return navBarPosition;
  22. }

通过上述代码

1、使用navigation_bar_window和navigation_bar填充布局

2、创建NavigationBarFrame 并且添加到windowManager中

2.2、导航栏图标加载及事件逻辑

2.2.1、布局文件添加

navigation_bar_window.xml:

     NavigationBarFrame,对DeadZone功能下的touch事件做了处理。

navigation_bar.xml:

  1. <com.android.systemui.navigationbar.NavigationBarView
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/navigation_bar_view"
  4. android:layout_height="match_parent"
  5. android:layout_width="match_parent"
  6. android:clipChildren="false"
  7. android:clipToPadding="false"
  8. android:background="@drawable/system_bar_background">
  9. <com.android.systemui.navigationbar.NavigationBarInflaterView
  10. android:id="@+id/navigation_inflater"
  11. android:layout_width="match_parent"
  12. android:layout_height="match_parent"
  13. android:clipChildren="false"
  14. android:clipToPadding="false" />
  15. </com.android.systemui.navigationbar.NavigationBarView>

NavigationBarInflaterView:

  1. protected void onFinishInflate() {
  2. super.onFinishInflate();
  3. inflateChildren();  //载导航栏布局文件
  4. clearViews();
  5. inflateLayout(getDefaultLayout());
  6. }
  1. private void inflateChildren() {
  2. removeAllViews();
  3. mHorizontal = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout,
  4. this /* root */, false /* attachToRoot */);
  5. addView(mHorizontal); //载导0度航栏布局文件
  6. mVertical = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_vertical,
  7. this /* root */, false /* attachToRoot */);
  8. addView(mVertical);  //载导90度航栏布局文件
  9. updateAlternativeOrder();
  10. }
  1. protected void inflateLayout(String newLayout) {
  2. ……
  3. inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),
  4. false /* landscape */, true /* start */);
  5. inflateButtons(start, mVertical.findViewById(R.id.ends_group),
  6. true /* landscape */, true /* start */);
  7. inflateButtons(center, mHorizontal.findViewById(R.id.center_group),
  8. false /* landscape */, false /* start */);
  9. inflateButtons(center, mVertical.findViewById(R.id.center_group),
  10. true /* landscape */, false /* start */);
  11. addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));
  12. addGravitySpacer(mVertical.findViewById(R.id.ends_group));
  13. inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),
  14. false /* landscape */, false /* start */);
  15. inflateButtons(end, mVertical.findViewById(R.id.ends_group),
  16. true /* landscape */, false /* start */);
  17. updateButtonDispatchersCurrentView();
  18. }
  1. protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,  boolean start) {
  2. LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
  3. View v = createView(buttonSpec, parent, inflater);
  4. ……
  5. v = applySize(v, buttonSpec, landscape, start);
  6. parent.addView(v);
  7. ……
  8. return v;
  9. }
  1. View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {
  2. View v = null;
  3. String button = extractButton(buttonSpec);
  4. if (LEFT.equals(button)) {
  5. button = extractButton(NAVSPACE);
  6. else if (RIGHT.equals(button)) {
  7. button = extractButton(MENU_IME_ROTATE);
  8. }
  9. if (HOME.equals(button)) {
  10. v = inflater.inflate(R.layout.home, parent, false);
  11. else if (BACK.equals(button)) {
  12. v = inflater.inflate(R.layout.back, parent, false);
  13. else if (RECENT.equals(button)) {
  14. v = inflater.inflate(R.layout.recent_apps, parent, false);
  15. else if
  16. ……
  17. return v;
  18. }

1、getDefaultLayout决定导航栏显示哪些控件。

一般情况下是home,recent,back这三个键,如果需要加其他的就在这配置,同时在createView添加对应的布局文件

2、createView方法创建对应的布局文件,并且添加到导航栏中。

2.2.2、资源文件添加、点击触摸事件

1、NavigationBarView.java(图标资源文件加载)

        reloadNavIcons( ) à updateIcons(Configuration.EMPTY) à 

2、NavigationBar.java(事件处理)

     prepareNavigationBarView()
  1. private void prepareNavigationBarView() {
  2. mNavigationBarView.reorient();
  3. ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
  4. recentsButton.setOnClickListener(this::onRecentsClick);
  5. recentsButton.setOnTouchListener(this::onRecentsTouch);
  6. ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
  7. homeButton.setOnTouchListener(this::onHomeTouch);
  8. reconfigureHomeLongClick();
  9. ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
  10. accessibilityButton.setOnClickListener(this::onAccessibilityClick);
  11. accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
  12. updateAccessibilityServicesState(mAccessibilityManager);
  13. ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton();
  14. imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick);
  15. updateScreenPinningGestures();
  16. }

参考链接:

SystemUI虚拟导航键加载流

SystemUI之NavigationBar

SystemUI之NavigationBar导航栏相关推荐

  1. Framework定制系列(一)-----SystemUI NavigationBar导航栏上滑返回Launcher

    1. NavigationBar导航栏上滑解决方案 代码路径:frameworks/base/services/core/java/com/android/server/wm/DisplayPolic ...

  2. 红橙Darren视频笔记 builder设计模式 navigationbar 导航栏第二版

    1.builder设计模式简介 builder的实际应用的典型案例有AlertDialog和OKHttp 例如 // AlertDialogAlertDialog alertDialog = new ...

  3. 微信小程序自定义navigation-bar导航栏(自适应安卓苹果)

    最近在写商城,中途遇到了需要自定义修改导航栏的操作,大概是如下图接过样子的,于是想手写一份,但我发现右上角的分享按钮在不同设备离顶部的距离是不一样的,于是找了下官方划水员写的文档(点这里查看),(⊙o ...

  4. IOS 学习笔记 Toolbar NavigationBar 导航栏 工具栏

    Toolbar使用gif图展示效果图: NavigationBar使用gif效果图 导航栏和工具栏(UIToolbar and NavigationBar) 工具栏和导航栏实际上是有很大差距的,这里放 ...

  5. 【微信小程序】学习笔记-----navigation-bar导航栏

    微信官方文档----小程序 微信小程序底部的导航栏不需要自己画,通过配置即可 先配置list数组,tab的列表 在app.json中与其他项平级,当输入tabBar的时候会自动填补齐全,这里要注意,控 ...

  6. 基于CarSystemUI实现左侧导航栏NavigationBar及下拉面板定制开发1——Android10智能座舱

    文章目录 前言 一.需求说明 二.修改方案 1.基于需求的两种设计构想 2.修改正确的高度及宽度 三.CarSystemUI 1.CarOS框架关于CarSystemUI的介绍 2.替换CarSyst ...

  7. html导航图片滚动条,CSS实现导航栏底部动态滚动条效果

    预习了CSS3部分的新知识,想着在不使用JS的情况下实现导航栏滚动条效果,如下: 实现滚动条效果,其实就是在 标签中让元素的宽度由0变化到100%,代码很简单,如下所示: CSS样式部分: ul.na ...

  8. Android SystemUI之NavigationBar,导航栏(四)

    Android  SystemUI系列: 1.Android  SystemUI之启动流程(一) 2.Android SystemUI之StatusBar,状态栏(二) 3.Android Syste ...

  9. java屏蔽虚拟按键代码_Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar...

    场景分析, 为了完全实现沉浸式效果,在进入特定的app后可以将导航栏移除,当退出app后再次将导航栏恢复.(下面将采用发送广播的方式来移除和恢复导航栏) ps:不修改源码的情况下,简单的沉浸式效果实现 ...

最新文章

  1. 卷积神经网络(CNN)_相关知识
  2. python使用方法-Python的使用方法
  3. 【转】你所不知道的HTML head/ 头标签
  4. ROS 总结(一):ROS系统框架
  5. 谈谈主机和存储连接的多路径技术
  6. 学院派CAD工具箱及CAD调用外部应用程序的方法
  7. Java加载sklearn训练好的模型进行预测(无法搞定)
  8. NET问答: 如何在 dynamic 集合上使用 Linq ?
  9. 命令行下Apache日志统计举例
  10. java实现语音聊天_java 语音聊天核心代码
  11. dos批处理命令详解(转)
  12. 正则表达式 两个符号的字段_Tableau正则提取字段部分内容
  13. 代码管理学:对于重写,四种人的不同态度
  14. 表的主键用数字还是UUID
  15. php圆角的度数计算公式,弧度和角度的换算器(度数换算计算器)
  16. 当不知轴承型号时如何寻找轴承故障频率_电机轴承的故障诊断与失效分析
  17. Rosalind第83题:Inferring Genotype from a Pedigree
  18. 基于O-RAN的无线云网络
  19. 小日期时间型_利于就业的汽车拆解技术服务师证报名时间、考试流程分几个级别?...
  20. C#压缩、解压缩文件(夹)(rar、zip)

热门文章

  1. my visitor
  2. 计算机类核心期刊排名(国内)
  3. sshpass报错Host key verification failed
  4. Python3群聊聊天室
  5. javaScript搜索框
  6. 如何用python画散点图矩阵_Python的散点图竟然能画这么好看
  7. 1036. 跟奥巴马一起编程(15)
  8. 疾病研究:重症肌无力医师指南
  9. layui解决数据表格右侧有空白现象
  10. 修改计算机管理员密码,该怎么改电脑administrator密码