AOSP Android14 Launcher3——底部任务栏Taskbar详解

前言:Launcher3中底部Taskbar和Navbar,或者说中文里面的术语导航栏,这几个词是很容易让人混淆的地方。本文要介绍的是Taskbar。从字面上意思来看,Taskbar就是任务栏,任务栏是Launcher3中一个重要的组件,尤其是在大屏平板设备上。

Taskbar的UI 形态

Taskbar在Launcher3中到底是指哪部分?

直接上图:


在屏幕底部显示的带有应用图标的部分就是Taskbar中的一部分,从上面LayoutInspector中可以看到,底部高度为161dp的View就是Taskbar。

在Launcher中,Taskbar的视图类是TaskbarDragLayer。

Taskbar有两种状态,一种是上图中完全展开的形态,有个术语叫UnStash状态,还有一种是只有底部一个bar条的形态,这种叫Stash状态。

Taskbar的显示逻辑与流程

核心目标:

Taskbar 旨在为大屏幕设备(平板电脑、折叠屏)提供类似桌面操作系统的体验,在应用运行时提供一个常驻或可按需访问的应用启动器和导航栏。

关键组件和控制器:

  1. TaskbarManager.java: 这是 Taskbar 的全局管理器

    • 职责: 决定是否应该在当前设备和配置下启用 Taskbar。监听设备状态变化(如屏幕旋转、折叠状态、导航模式切换)来判断是否需要创建或销毁 Taskbar UI。
    • 流程:TaskbarManager 确定需要 Taskbar 时(通常在 LauncherActivity 或类似上下文启动时),它会创建 TaskbarActivityContext
  2. TaskbarActivityContext.java: Taskbar 的上下文环境

    • 职责: 这是 Taskbar UI 实际运行的 Context。它负责创建 Taskbar 的主视图(TaskbarView)和 DragLayer (TaskbarDragLayer),并初始化所有的 Taskbar 控制器 (TaskbarControllers)。它还处理与 Launcher Activity 的生命周期绑定、资源获取、权限检查等。
    • 流程:
      • onCreate() 中,它会加载 Taskbar 布局 (R.layout.taskbar)。
      • 创建 TaskbarControllers 实例,该实例会聚合所有其他的子控制器。
      • 调用 TaskbarControllers.init() 来初始化所有子控制器,并建立它们之间的引用。
  3. TaskbarControllers.java: 控制器聚合器

    • 职责: 持有所有其他 Taskbar 子控制器的引用,方便它们之间相互访问和协调。提供一个统一的初始化 (init) 和销毁 (onDestroy) 入口。
    • 流程:init() 中,它会按顺序创建并初始化各个子控制器,如 TaskbarViewControllerTaskbarStashControllerNavbarButtonsViewController 等。
  4. TaskbarView.java: 核心 UI 视图

    • 职责: 继承自 ViewGroup,是容纳 Taskbar 上所有图标(应用、文件夹、预测应用)的容器。它处理图标的布局、添加、移除和更新。
    • 显示:TaskbarActivityContext 创建并添加到其 TaskbarDragLayer 中。
  5. TaskbarViewController.java: TaskbarView 的控制器

    • 职责: 管理 TaskbarView 的内容和视觉状态。
      • 从数据模型(通过 TaskbarModelCallbacks)获取应用列表并绑定到 TaskbarView 上。
      • 处理图标的点击、长按(弹出菜单,通过 TaskbarPopupController)。
      • 控制图标的 Alpha、Scale、TranslationY 等属性,用于配合 TaskbarStashController 实现收起/展开动画。
    • 流程:TaskbarControllers.init() 中被初始化,并获取对 TaskbarView 的引用。监听数据模型变化来更新 UI。
  6. TaskbarStashController.java: 收起/展开逻辑的核心控制器

    • 职责: 这是控制 Taskbar 是否应该显示为完整条、收起成一个细条 (Handle) 或完全隐藏的决策中心和动画协调者
    • 原理 (State Flags): 维护一个整数状态 mState,通过位标志 (FLAG_*) 来记录各种影响 Taskbar 可见性的条件,例如:
      • FLAG_IN_APP: 是否在第三方应用中。
      • FLAG_STASHED_IN_APP_SYSUI: 系统 UI(如通知面板)是否要求收起。
      • FLAG_STASHED_IN_APP_IME: 输入法是否显示。
      • FLAG_IN_STASHED_LAUNCHER_STATE: 当前 Launcher 状态是否要求收起 (如 AllApps)。
      • FLAG_STASHED_IN_APP_AUTO: 是否是瞬态 Taskbar (Transient) 且当前处于自动隐藏状态。
      • FLAG_STASHED_DEVICE_LOCKED: 设备是否锁定。
      • ... 等等。
    • 决策 (mIsStashedPredicate): 通过一个 IntPredicate (一个函数式接口,输入 int 返回 boolean) 来判断当前 mState 的组合是否意味着 Taskbar 应该 处于收起状态 (mIsStashed)。
    • 状态应用 (applyState, createApplyStateAnimator): 当外部事件(如 Launcher 状态改变、系统 UI 状态改变、用户交互等)调用 updateStateForFlag() 更新了 mState 后,会调用 applyState()applyState() 会比较新的预期收起状态 (mIsStashedPredicate.test(newState)) 和当前的视觉状态 (mIsStashed)。
      • 如果状态不一致,则调用 createAnimToIsStashed() 创建一个 AnimatorSet 来驱动 Taskbar UI 元素的动画(背景、图标、Handle 的 Alpha、Scale、Translation)。
      • 动画会平滑地过渡到新的收起/展开状态。
    • 动画类型 (@StashAnimation): 支持多种不同的收起/展开动画效果(TRANSITION_DEFAULT, TRANSITION_HOME_TO_APP, TRANSITION_HANDLE_FADE 等),根据触发场景选择不同的动画插值器和时序。
    • 瞬态 Taskbar (Transient): 对瞬态 Taskbar 有特殊处理逻辑,包括自动隐藏计时器 (mTimeoutAlarm) 和通过 updateAndAnimateTransientTaskbar() 进行显式控制。
  7. StashedHandleViewController.java & StashedHandleView.java: 收起状态 Handle 的控制器和视图

    • 职责:TaskbarStashController 决定收起 Taskbar 时,StashedHandleViewController 负责显示和管理 StashedHandleView(那个白色细条)。它控制 Handle 的 Alpha 和 Scale,实现显示/隐藏以及 Hint 动画(轻微放大提示可以展开)。
  8. TaskbarLauncherStateController.java: Launcher 状态转换器

    • 职责: 监听 Launcher 的状态变化(StateManager.addStateListener),并将 Launcher 状态(如 NORMAL, OVERVIEW, ALL_APPS)转换为 TaskbarStashController 能理解的状态标志 (FLAG_IN_STASHED_LAUNCHER_STATE, FLAG_IN_APP, FLAG_IN_OVERVIEW)。
    • 流程: 当 Launcher 状态切换时,它会调用 TaskbarStashController.updateStateForFlag() 来更新相应的标志,然后触发 TaskbarStashController.applyState() 来应用变化。
  9. TaskbarInsetsController.kt: 窗口 Insets 控制器

    • 职责: 根据 Taskbar 的收起/展开状态和类型(持久/瞬态),计算应该向应用报告的窗口 Insets(底部导航栏区域)。
    • 原理: 当 Taskbar 展开时,报告完整的高度;当收起时,通常报告 mStashedHeight(Handle 的高度),或者在某些特定情况(如持久 Taskbar + IME)下报告 0。它确保应用的内容能够正确地避让 Taskbar。
  10. TaskbarStashViaTouchController.kt: 触摸交互控制器

    • 职责: 处理用户直接在 Stashed Handle 或 Taskbar 背景区域的触摸事件,用于触发/取消瞬态 Taskbar 的自动隐藏计时器,或者启动 Hint 动画。
  11. 其他控制器:

    • NavbarButtonsViewController.java: 管理导航按钮(Back, Home, Recents)的显示、布局和点击事件。
    • TaskbarDragLayerController.java: 管理 Taskbar 的背景、圆角和 Y 轴偏移。
    • TaskbarDragController.java: 处理 Taskbar 内部或涉及 Taskbar 的拖放操作。
    • TaskbarKeyguardController.java: 处理锁屏状态对 Taskbar 的影响。
    • TaskbarPinningController.kt: 处理用户固定/取消固定持久 Taskbar 的设置。
    • TaskbarAutohideSuspendController.java: 管理自动隐藏功能的暂停状态。
    • ... 等等。

加载与显示流程总结:

  1. 启动: LauncherActivity (或其他宿主) 启动。
  2. TaskbarManager 决策: TaskbarManager 判断当前设备配置是否需要 Taskbar。
  3. 创建 Context: 如果需要,TaskbarManager 创建 TaskbarActivityContext
  4. Context 初始化: TaskbarActivityContext 加载布局,创建 TaskbarDragLayerTaskbarView
  5. 控制器聚合: TaskbarActivityContext 创建 TaskbarControllers
  6. 子控制器初始化: TaskbarControllers.init() 逐个创建并初始化所有子控制器 (TaskbarViewController, TaskbarStashController, NavbarButtonsViewController 等),并建立它们之间的引用。
  7. 初始状态设定:
    • TaskbarStashController 根据初始条件(是否 Setup、是否 Phone Mode、是否瞬态、持久化设置等)设置初始的 mState 标志。
    • TaskbarLauncherStateController 获取当前的 Launcher 状态,并更新 TaskbarStashController 的相应标志。
  8. 首次应用状态: TaskbarStashController.applyState(0) 被调用,根据初始的 mState 计算出 Taskbar 应该是收起还是展开,并立即设置 UI 到对应的视觉状态(没有动画)。
  9. Insets 更新: TaskbarInsetsController 根据初始状态计算并向系统报告窗口 Insets。
  10. 数据绑定: TaskbarViewController 开始从模型加载数据并绑定到 TaskbarView 上显示图标。
  11. 事件监听与状态更新:
    • TaskbarLauncherStateController 监听 Launcher 状态变化。
    • TaskbarStashController 监听系统 UI 状态变化 (updateStateForSysuiFlags)。
    • TaskbarKeyguardController 监听锁屏状态。
    • TaskbarPinningController 监听用户 pinning 设置。
    • TaskbarStashViaTouchController 监听触摸事件。
    • 当任何影响可见性的状态发生变化时,对应的控制器会调用 TaskbarStashController.updateStateForFlag()
  12. 动画应用: TaskbarStashController.applyState() 被调用,如果计算出的收起/展开状态与当前视觉状态不同,则创建并启动动画 (mAnimator) 来平滑过渡。
  13. 持续运行: Taskbar 进入运行状态,响应用户交互(点击、长按、拖拽)、系统事件和状态变化,并由 TaskbarStashController 动态调整其可见性。

核心原理:

Taskbar 的核心原理是基于状态的可见性控制动画协调

  • 状态驱动: TaskbarStashController 通过维护一组状态标志 (mState) 来集中管理所有影响 Taskbar 是否应该收起的因素。
  • 解耦: 每个子控制器负责监听和更新自己相关的状态标志,将具体逻辑与最终的可见性决策解耦。
  • 集中决策: TaskbarStashController 根据所有标志的组合,使用 mIsStashedPredicate 做出最终的收起/展开决策。
  • 动画协调: TaskbarStashController 负责创建和管理收起/展开的 AnimatorSet,该动画集会同时驱动 Taskbar 背景、图标和 Handle 等多个 UI 元素的属性变化,实现协调一致的视觉过渡。
  • Insets 同步: TaskbarInsetsController 确保窗口 Insets 与 Taskbar 的状态(以及动画预期)保持一致,让应用能够正确布局。

这种设计使得 Taskbar 能够灵活地响应各种复杂的系统和用户状态变化,同时保持 UI 的流畅性和一致性。

相关推荐
Mr_Fingerling13 小时前
Android12编译x86模拟器报找不到userdata-qemu.img
framework·aosp·android12·x86模拟器
千里马学框架24 天前
安卓15/aosp15/lineage21使用brunch编译老是报错OOM内存不足
android·车载系统·framework·系统开发·aosp·lineage
hedalei4 个月前
RK3576 Android14编译OTA包提示java.lang.UnsupportedClassVersionError问题
android·android14·rk3576
冬瓜神君4 个月前
Android14 AOSP支持短按关机
android·aosp
Sgq丶5 个月前
Android 13 aosp Launcher 隐藏“壁纸和样式“入口
android·aosp·launcher3
ItJavawfc5 个月前
Launcher3 去掉桌面搜索索框
launcher3·去掉搜索框·谷歌搜索框
Just_Paranoid6 个月前
Android 虚拟化框架(AVF)指南
android·google·虚拟化·aosp·avf
Kwanvin7 个月前
Android13 Hotseat客制化--Hotseat修改布局、支持滑动、去掉开机弹动效果、禁止创建文件夹
android·java·launcher3·hotseat
Kwanvin8 个月前
仿华为车机UI--图标从Workspace拖动到Hotseat同时保留图标在原来位置
android·java·ui·华为·launcher3