我现在开发aosp12的launcher3,单独打包运行它的最近任务模块,遇到一个bug。最近任务列表左右滑动时候,最后一个app的item,它的app缩略图不跟随item滑动,而是脱离了item,固定显示在屏幕中间。遮挡其他item 。这个有什么处理方式呢?
搞了好久,修改很多东西都还是不完善。后面找一个简单粗暴的方式。关闭 Live Tile。
关闭 Live Tile 的影响
1. 视觉体验变化 最近任务视图中不再显示应用的实时动态画面 改为显示静态的应用快照/缩略图 从应用切换到最近任务的动画效果变得不那么流畅
2. 性能影响 内存占用减少:不需要持续渲染实时画面,降低内存使用 电量消耗降低:减少了 GPU 和 CPU 的持续工作负载 发热改善:系统资源使用更少,设备温度更低
3. 功能限制 无法实时查看应用当前状态(如视频播放、游戏进程等) 预览图像是应用暂停时的快照,不是实时状态 从最近任务返回应用时的动画体验可能略有不同
4. 兼容性考虑 在某些设备上可能有更好的稳定性 可能解决某些应用的渲染冲突问题 对低性能设备更友好。
## 回答
你这个现象**非常像 Quickstep 的「Live Tile」在独立最近任务里跑坏了**:
> 只有最后一个卡片的缩略图不跟着 item 滚,而是钉在屏幕中间,把别的卡片盖住。
这基本就是 **运行中任务的“活卡片”(live tile)** 表现异常:
正常 AOSP 里,当前前台 app 在 Recents 里可以用真正的 app Surface 做预览(Live Tile),不是单纯的截图。这个 Surface 是通过 `BaseSwipeUpHandler + TaskViewSimulator + SyncRtSurfaceTransactionApplier` 一套链路控制的。([Android Git Repositories](https://android.googlesource.com/platform/packages/apps/Launcher3/%2B/0e7fe1a83d1982b25f89a8a146386d05435f05db/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java?utm_source=chatgpt.com))
你现在是 **把 Launcher3 的最近任务模块单独抽出来跑(SEPARATE_RECENTS_ACTIVITY / FallbackRecentsView)**,坐标系、动画时序稍有不一致,就会出现:
- 卡片 View(TaskView)作为 child 在 RecentsView 里左右滑动
- 但 Live Tile 的 Surface 其实是挂在另外一层(整个 Activity 的 decor / DragLayer),用的是**屏幕坐标**,没有跟着 TaskView 的平移更新
- 于是看起来:**最后一个 item 的“缩略图”不动,永远在屏幕中间,遮住其他卡片**
AOSP 自己也有类似 bug 的历史记录,比如有个改动就叫:
> “[Live Tile] App surface is above launcher even after reaching Overview”([Android Git Repositories](https://android.googlesource.com/platform/packages/apps/Launcher3/%2B/b58eb1bc63f10dd8f1a97043cd0ced474c770f33%5E%21/?utm_source=chatgpt.com))
说白了就是:应用 Surface 总是盖在 Launcher/Recents 上方。
---
## 一步一步来,先验证是不是 Live Tile 惹的祸
你可以先做两个小实验:
1. **看是不是“当前前台 app 那张卡片”有问题**
- 打开 App A → 进最近任务 → 左右滑动
- 观察:是不是**当前前台的那一张卡**(通常在中间 / 最右)缩略图脱离卡片、固定在中间?
- 换一个前台 app 试几次,如果每次都是“当前 app 那张卡炸了”,就几乎可以确定是 Live Tile。
2. **看只有最近一个任务有问题,还是所有卡片都有问题**
- 一般只有**一个**“活的” Surface(running task),其他都是截图(snapshot),所以其它卡片正常,只有这张卡出问题,很符合 Live Tile 坐标没同步的特征。
---
## 方案 1:粗暴但靠谱——直接关掉 Live Tile
对“独立打包的 Recents 模块”来说,其实 **完全可以不用 Live Tile**,用截图就够了,而且 AOSP 里 Live Tile 本身就容易出坑。
在 Launcher3 的 `FeatureFlags` 里有一个开关:
```java
// src/com/android/launcher3/config/FeatureFlags.java
public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
"ENABLE_QUICKSTEP_LIVE_TILE", true,
"Enable live tile in Quickstep overview");
```
([Android Git Repositories](https://android.googlesource.com/platform/packages/apps/Launcher3/%2B/9a5f99bfe6/src/com/android/launcher3/config/FeatureFlags.java?autodive=0%2F%2F))
你可以直接把默认值改成 `false`:
```java
public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
"ENABLE_QUICKSTEP_LIVE_TILE", false,
"Enable live tile in Quickstep overview");
```
重新编译最近任务模块 / Launcher3 后:
- Recents 里所有卡片都用普通的 `TaskThumbnailView`(纯截图)来画
- 不再去用 WindowManager 的 live surface
- 缩略图自然就跟着 TaskView 一起平移,不会再“钉死屏幕中间”
**这个是我最推荐你先尝试的方案**,原因:
- 修改点极小:只动一个布尔默认值
- 对你的“独立 Recents APK”最友好,不用到处改手势动画/Surface 逻辑
- 行为上用户很难察觉差别(大多数侧移 Recents 自定义 ROM 都直接关了 Live Tile)
---
## 方案 2:你想保留 Live Tile,那就要同步它的坐标
如果你坚持要 Live Tile(比如想保留“当前 app 在 Recents 中还在运行”的动态效果),那就要搞清楚两类东西的坐标:
- **View 层的 TaskView**:它跟着 `RecentsView (PagedView)` 的 `scrollX/translationX` 走
- **Live Tile 的 Surface**:通过 `TaskViewSimulator` / `TransformParams` / `SyncRtSurfaceTransactionApplier` 用矩阵单独控制
在集成的 Launcher+Recents 模式下,这两套坐标同步是由 `BaseSwipeUpHandler` 在手势过程中不断更新的([Android Git Repositories](https://android.googlesource.com/platform/packages/apps/Launcher3/%2B/0e7fe1a83d1982b25f89a8a146386d05435f05db/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java?utm_source=chatgpt.com))。
你现在把 Recents 单独跑,很容易漏掉这几类更新时机:
1. **RecentsView 水平滚动的时候**
- 你需要在 `RecentsView.onScrollChanged` 或类似回调里,通知当前 running task 的 `TaskViewSimulator`,重新算一次 matrix,并把新的 transform 通过 `applySurfaceParams()` 下发给 Surface。
- 否则 Surface 还是停在原来的“中心位置”,TaskView 自己滑走了,就分家了。
2. **切到 Overview 完成之后**
- 原本在一体化 Launcher 里,`BaseSwipeUpHandler` 会在动画结束时把 running task 的 Surface 重新对齐到对应的 TaskView 卡片上。
- 你改成独立 Activity 之后,如果手势流程改了、或者复用不完整,很可能导致这一步没被调用,Surface 仍然保持“居中”。
3. **确认 Live Tile attach 的父容器**
- 建议用 Layout Inspector / 调试 log 看一下:
- TaskView 这张卡本身是在 `RecentsView` 里
- Live Tile 的 Surface 可能挂在 DecorView / DragLayer 的某个 `ViewGroup` 上
- 如果父容器不是跟着 `RecentsView` 一起移动的层,坐标就一定会出问题。
这条路改动会比较多,调试也费时间,我建议你 **先用方案 1 把 Live Tile 干掉,保证功能正确,�考虑慢慢修 Live Tile 的动画链路**。
---
## 方案 3:其它可能的坑(可以顺手自查一下)
即便关掉 Live Tile,也可以顺手检查几项基础东西,防止还有别的坑:
1. **最后一个 TaskView 的 LayoutParams 是否异常**
- 看下是不是只有最后一个卡片用了 `MATCH_PARENT`、特殊 margin、或手动 `setX()/setTranslationX()` 之类的逻辑。
2. **缩略图是不是被错误地 add 到了别的 ViewGroup**
- 正常情况下缩略图 View(`TaskThumbnailView`)必须是 `TaskView` 的 child。
- 如果你在移植时改过 layout,有可能不小心加到了更外层。
3. **是否打开了 `SEPARATE_RECENTS_ACTIVITY` 这个 flag**
- AOSP 有个 `SEPARATE_RECENTS_ACTIVITY` 开关,用来启用独立的 recents Activity([Android Git Repositories](https://android.googlesource.com/platform/packages/apps/Launcher3/%2B/9a5f99bfe6/src/com/android/launcher3/config/FeatureFlags.java?autodive=0%2F%2F))
- 如果你是自己拆模块,而没按它预期的方式集成,Live Tile 那套逻辑就更容易对不齐。更推荐“`SEPARATE_RECENTS_ACTIVITY` + `ENABLE_QUICKSTEP_LIVE_TILE=false`”这种组合。
---
## 建议先做哪一步?
**我推荐你按这个顺序来:**
1. 先确认问题卡片是不是“当前前台 app”的那张(基本能坐实 Live Tile)。
2. 直接改 `FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE` 默认值为 `false`,重新编译你的 recents APK 测一下:
- 如果问题立刻消失 → 100% 是 Live Tile 导致的,先这样用完全 OK。
3. 如果以后你真想把 Live Tile 搞通,再专门梳理一遍:
- `BaseSwipeUpHandler` / `TaskViewSimulator` / `RecentsAnimationCallbacks` 这一条链
- 确保在 **scroll / layout / 动画结束** 这几个关键点都对 running task 的 Surface 做了位移同步。
若要修改,具体看看 RecentsActivity / RecentsView / FeatureFlags 代码,改动,以修 Live Tile 坐标问题。
1万+

被折叠的 条评论
为什么被折叠?



