android T分屏 Launcher RecentsView部分介绍/android framework手机车机系统开发

AOSP Android14 Launcher3——RecentsView最近任务数据加载 最近任务的数据加载流程 阅读详情
AI摘要

该文详细解析了Android系统中实现桌面分屏功能的第一步动画过程,包括点击Splittop按钮后的TaskView动画,涉及createTaskDismissAnimation、FloatingTaskView等,以及如何构建和启动相关动画。在用户选择第二个应用后,通过SplitSelectStateController启动真正的分屏任务。整个过程涉及到系统UI和系统服务的交互。

1 桌面部分第一阶段动画:

b站免费视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
在这里插入图片描述
桌面点击这个Split top按钮的onClick后触发自己进程的view相关的动画:
在这里插入图片描述

点击之后会有相关动画的准备工作:
点击后会动画进入如下图一样状态,这个短信app放到上面,下面多任务依旧是多任务,位置确实变化了
在这里插入图片描述

相关动画调用栈:

createTaskDismissAnimation:2975, RecentsView (com.android.quickstep.views)
createSplitSelectInitAnimation:4022, RecentsView (com.android.quickstep.views)
handleSplitSelectionState:120, RecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimationInternal:96, RecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimation:87, BaseRecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimation:53, BaseRecentsViewStateController (com.android.launcher3.uioverrides)
createAnimationToNewWorkspaceInternal:324, StateManager (com.android.launcher3.statemanager)
goToStateAnimated:259, StateManager (com.android.launcher3.statemanager)
goToState:247, StateManager (com.android.launcher3.statemanager)
goToState:150, StateManager (com.android.launcher3.statemanager)
goToState:143, StateManager (com.android.launcher3.statemanager)
initiateSplitSelect:182, LauncherRecentsView (com.android.quickstep.views)
initiateSplitSelect:1541, TaskView (com.android.quickstep.views)
onClick:132, TaskShortcutFactory$SplitSelectSystemShortcut (com.android.quickstep)
lambda$addMenuOption$1:254, TaskMenuView (com.android.quickstep.views)
run:-1, TaskMenuView$$ExternalSyntheticLambda2 (com.android.quickstep.views)
finishRecentsAnimation:4535, RecentsView (com.android.quickstep.views)
lambda$addMenuOption$2:252, TaskMenuView (com.android.quickstep.views)
run:-1, TaskMenuView$$ExternalSyntheticLambda1 (com.android.quickstep.views)
switchToScreenshot:4961, RecentsView (com.android.quickstep.views)
lambda$addMenuOption$3$com-android-quickstep-views-TaskMenuView:251, TaskMenuView (com.android.quickstep.views)
onClick:-1, TaskMenuView$$ExternalSyntheticLambda5 (com.android.quickstep.views)
performClick:7506, View (android.view)
performClickInternal:7483, View (android.view)
-$$Nest$mperformClickInternal:-1, View (android.view)
run:29335, View$PerformClick (android.view)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)

因为代码太多,只对上半部分的TaskView动画进行相关的说明:
这里createTaskDismissAnimation其实就是上面那个短信应用上半屏幕部分显示的动画构建

/**
     * Places an {@link FloatingTaskView} on top of the thumbnail for {@link #mSplitHiddenTaskView}
     * and then animates it into the split position that was desired
     */
    private void createInitialSplitSelectAnimation(PendingAnimation anim) {
        mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
                mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);

        RectF startingTaskRect = new RectF();
        if (mSplitHiddenTaskView != null) {
            mSplitHiddenTaskView.setVisibility(INVISIBLE);//把TaskView设置不可见
            //要创建一个TaskView的副本,并且要把这个副本进行相关的动画播放显示在最顶端一个小区域
            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitHiddenTaskView.getThumbnail(),
                    mSplitHiddenTaskView.getThumbnail().getThumbnail(),
                    mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
            mFirstFloatingTaskView.setAlpha(1);
            //根据相关的初始化尺寸来构建对应anim
            mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
                    true /* fadeWithThumbnail */, true /* isStagedTask */);
        } else {
         
        }
        anim.addEndListener(success -> {
            if (success) {
                mSplitToast.show();
                //动画播放完成后,显示出一个Toast "Tap another app to use split-screen"
            }
        });
    }

其他TaskView动画就不进行相关的介绍了,都在这调用堆栈里面,到此时分屏在桌面多任务完成了第一步,把TaskView放到顶部(上屏),接下来要等待用户来手动选择一个下屏app,才可以构成真正意义的分屏。
在这里插入图片描述

2 桌面选择点击底部TaskView点击,及相关动画启动

底部点击TaskView触发动画流程相对比较简单:

 private void onClick(View view) {
        if (confirmSecondSplitSelectApp()) {
            return;
        }
}
 private boolean confirmSecondSplitSelectApp() {
        int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
        TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
        //调用到了RecentsView的confirmSplitSelect方法
        return getRecentsView().confirmSplitSelect(this, container.getTask(),
                container.getIconView(), container.getThumbnailView());
    }

	//方法进行相关的动画准备和启动
     public boolean confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
            TaskThumbnailView thumbnailView) {
        //省略
        mSplitSelectStateController.setSecondTask(task);//设置底部区域要显示的task
        RectF secondTaskStartingBounds = new RectF();//初始化底部的区域
        Rect secondTaskEndingBounds = new Rect();
        Rect firstTaskStartingBounds = new Rect();//初始化顶部的区域
        Rect firstTaskEndingBounds = mTempRect;
        //获取动画时间
        int duration = mActivity.getStateManager().getState().getTransitionDuration(mActivity,
                false /* isToState */);
        PendingAnimation pendingAnimation = new PendingAnimation(duration);

        int halfDividerSize = getResources()
                .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
                //获取对应的一个上屏幕区域和下屏幕区域截至区域firstTaskEndingBounds,secondTaskEndingBounds
        mOrientationHandler.getFinalSplitPlaceholderBounds(halfDividerSize,
                mActivity.getDeviceProfile(),
                mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
                secondTaskEndingBounds);
		
		//获取当前的上屏幕区域坐标情况放入firstTaskStartingBounds
        mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
        //有了初始区域和结束区域,进行相关的动画配置
        mFirstFloatingTaskView.addAnimation(pendingAnimation,
                new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
                false /* fadeWithThumbnail */, true /* isStagedTask */);

//下屏部分和商品部分类是不再讲解
        mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                thumbnailView, thumbnailView.getThumbnail(),
                iconView.getDrawable(), secondTaskStartingBounds);
        mSecondFloatingTaskView.setAlpha(1);
        mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
                secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
          //进行动画结束监听,在动画结束时候才进行launchSplitTasks,即正式调用到systemui和systemserver让赶紧启动真正分屏
        pendingAnimation.addEndListener(aBoolean -> {
            mSplitSelectStateController.launchSplitTasks(
                    aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
        });
        if (containerTaskView.containsMultipleTasks()) {
            // If we are launching from a child task, then only hide the thumbnail itself
            mSecondSplitHiddenView = thumbnailView;
        } else {
            mSecondSplitHiddenView = containerTaskView;
        }
        mSecondSplitHiddenView.setVisibility(INVISIBLE);//下屏的TaskView要被隐藏
        pendingAnimation.buildAnim().start();//启动正式动画
        return true;
    }

正式调用systemui相关的shell接口进行操作真正的task相关分屏业务:

launchTasks:201, SplitSelectStateController (com.android.quickstep.util)
launchSplitTasks:124, SplitSelectStateController (com.android.quickstep.util)
lambda$confirmSplitSelect$24$com-android-quickstep-views-RecentsView:4081, RecentsView (com.android.quickstep.views)
accept:-1, RecentsView$$ExternalSyntheticLambda30 (com.android.quickstep.views)
onAnimationEnd:80, AnimatorListeners$EndStateCallbackWrapper (com.android.launcher3.anim)
:-1, Animator$AnimatorListener (android.animation)
endAnimation:1333, ValueAnimator (android.animation)
doAnimationFrame:1575, ValueAnimator (android.animation)
pulseAnimationFrame:1591, ValueAnimator (android.animation)
pulseFrame:1170, AnimatorSet (android.animation)
handleAnimationEvents:1153, AnimatorSet (android.animation)
doAnimationFrame:1053, AnimatorSet (android.animation)
doAnimationFrame:307, AnimationHandler (android.animation)
-$$Nest$mdoAnimationFrame:-1, AnimationHandler (android.animation)
doFrame:86, AnimationHandler$1 (android.animation)
run:1229, Choreographer$CallbackRecord (android.view)
run:1239, Choreographer$CallbackRecord (android.view)
doCallbacks:899, Choreographer (android.view)
doFrame:827, Choreographer (android.view)
run:1214, Choreographer$FrameDisplayEventReceiver (android.view)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)
SystemUI 调整Recents中全部清除按钮位置 RecentsView 阅读详情

相关推荐

最近任务Recents分析

最近任务Recent 启动 通过手势启动RecentsActivity 显示:在启动RecentsActivity之后,会显示最近任务列表 RecentsActivity.java:Recents显示Activity RecentsActivity继承了StatefulActivity,有些方法实现是在父类里面执行的,在onCreate()里面执行setupViews(),setupViews()中初始化了FallbackRecentsView,FallbackRecentsVie...

weixin_43832256的博客 3490

Android10.0 RecentsView-最近任务流程

最近任务 packages/apps/Launcher3/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java 遍历所有请求,并为新可见的任务加载关联的任务数据,并为不再可见的任务卸载关联的任务数据。 public void loadVisibleTaskData() 获取taskView数量 public int getTaskViewCount() 卸载当前可见任务中的所有关联数据 priva.

吉吉的博客 3706

Android 12.0 Launcher3定制化之最近任务的全部清除由左边移到下边显示

在最近12.0的产品开发中,在Launcher3的定制化开发中,在最近任务列表中,发现点击recents最近任务键后 显示的全部清除按键在左边 由于是横屏的产品显示在左边不太合理 所以要求显示在下边比较合理,所以要从Launcher3的显示流程来解决这个问题

安卓兼职framework和app工程师的博客 2201

Android 11 在重启的时候清除最近任务缓存

Android 11 在重启的时候清除最近任务缓存

qq_46524402的博客 1181

linux入侵排查-综合日志分析

2.分析攻击者首次成功登录web管理后台的时间 还可以知道攻击者可能是通过10.2.4.11这个跳板服务器跳过来的,然后我们继续排查,可以发现日志中POST请求大多都是1047字节,然后往后大多是300字节,POST请求的响应状态码有200和302这两个,其中的302是爆破成功后持续爆破产生的日志,再1047字节和300字节中间夹着一个978字节,就是200响应和302响应的中间。7.分析攻击者留下的持久化后门的时间和后门执行情况 排查计划任务,发现有一个计划任务还是被加密的,应该是反弹shell的。

chinese_cabbage0的博客 643

《第二十二篇》Cross-Attention:注意力机制详解-代码实现和公式详解《二》

本文详细介绍了Cross-Attention的原理、公式和实现。Cross-Attention用于Transformer解码器和Encoder-Decoder结构,通过查询向量(Q)与键、值向量(K、V)的交互实现序列对齐。核心公式为softmax(QK^T/√d_k)V,其中Q来自Decoder,K、V来自Encoder。文章还给出了多头注意力机制公式和PyTorch实现代码,包括投影计算、注意力分数计算和输出处理。代码示例展示了如何构建一个完整的Cross-Attention模块,并演示了其在解码器查询

guoguozgw的博客 2211

Android系统级开发进程清理功能的一些记录和发现(二)

基于Android 7.0的近期任务列表进程清理实现最近有小伙伴反应,上篇博客中提到的直接修改近期任务列表的方法在7.0的系统中无法使用,因为找不到onTaskViewDismissed()这个方法了。同时,RecentsActivity更新任务Tasks的方法和6.0相比也有很大的改变,具体改变请小伙伴自行研究,本文主要讲针对7.0改变实现进程清理的方法。 第一步、改造RecentsView纵观R

qwe749082787的博客 1406

【数字图像相关-OpenCorr学习笔记】Epipolar search原理+代码解析

OpenCorr是一个开源C++库,用于研究和开发数字图像相关(DIC)技术它提供了2D和立体声DIC的全功能模块,以及数字体积相关(DVC)。最近正在学习OpenCorr,为了更深层次地理解ICGN,我打算浅浅剖析Opencorr的代码,学习的过程中写下这篇学习笔记,以后忘记了还能回来看看。同时,作为一名在读研究生,希望能得到社区大佬的指点,以及跟同学们一起学习进步。这一期主要讲解Eipipolar search的原理,并且附上部分代码解析。

ywyywyy的博客 1356

Android11 最近任务Recents功能分析,分析的很彻底

Android11 最近任务Recents功能分析,分析的很彻底,值得浏览点赞。

wzx311的博客 1万+

【100%通过率】华为od 机试真题 C语言 实现【补种未成活胡杨】

近些年来,我国防沙治沙取得显著成果。某沙漠新种植N棵胡杨(编号1-N),排成一排。一个月后,有M棵胡杨未能成活。现可补种胡杨K棵,请问如何补种(只能补种,不能新种),可以得到最多的连续胡杨树?

MISAYAONE的博客 1654

VS2019编译配置Easy3D

VS2019编译配置Easy3D

dayuhaitang1的博客 2596

Launcher对RecentView展示TaskView详细分析-android framework车载车机手机系统开发

1、桌面调用到sysui获取Task信息,因为sysui中其实有分屏相关的TecentTask信息。2、sysui也是调用到atms进行RecentTask的信息获取。这里其实会调用的sysui的getRecentTasks进行查询。

learnframework的博客 1571

攻克反光难题!YOLOv9工业缺陷检测实战:高反光件、微小划痕精准识别(附抗反光代码+产线数据)

文章摘要:本文针对不锈钢、铝合金等高反光工业件的缺陷检测难题,提出了一套“硬件抗反光+YOLOv9小目标增强”的解决方案。通过分析反光干扰(镜面/漫反射)和微小划痕(0.1mm级)两大核心问题,详细介绍了500万像素工业相机+偏振光源的硬件配置方案,以及基于偏振图像融合和超分辨率放大的预处理方法。最终实现误检率1.2%、微小划痕检出率99.3%的工业级检测效果,并提供了可落地的代码实现和车间实测数据。(148字)

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1041

Android 7.1 启动分屏模式分析(SystemUI), 附应用启动分屏方法

平台 RK3288 + Android 7.1 切入点 在点击近期任务后, 长按任务会出现如下界面, 拖动任务到指定区域可以进入分屏模式(DOCK): 主窗体 com.android.systemui/.recents.RecentsActivity 布局 frameworks/base/packages/SystemUI/res/layout/recents.xml 核心View控件RecentView |-- frameworks/base/packages/SystemUI/src/co

ansondroider的博客 2206

双重机器学习模型中解释变量是连续变量的代码,看到好多都是0/1变量,如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!    📌 特别说明: 文中部分技术问题来源于真实生产环境及网络公开案例,均经过精挑细选与系统化整理,并结合多位一线资深架构师和工程师多年实战经验沉淀,提

**My Coding Family** 853

高质量文献综述原来这么写!借助Gemini 3 Pro+四步法,手把手教你写出有逻辑深度的综述

总结与展望先总结现状,说明前人已经做到什么地步了,再指出缺口,前人没解决什么问题、方法有什么局限等等,最后再在这个缺口的基础上,提出你的未来研究方向。当你有个复杂的研究题目,但没办法拆解出关键词,就可以让Gemini 3 Pro来辅助帮你拆解,并帮你写专业的检索式,若是找英文文献,还能帮你将中文关键词翻译成地道的专业术语。做文献笔记,可以建立文献笔记矩阵,可以用Excel建个表格,横向是文献,纵向是关键要素,包括作者/年份、研究问题/假设、理论框架/模型、研究方法/数据来源、核心结论、局限性/Gap。

智能AI让学术科研更容易 992

Launcher3最近任务遥控切换动画

本文主要介绍如何分析遥控模式下,最近任务卡片切换时的动画缺失的问题,并最终解决该问题。

rophy___的博客 1483

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

android最近任务列表,删除某个应用操作

1、SystemUI工程 RecentsActivity.java     protected void onCreate(BundlesavedInstanceState) {        getWindow().addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR);    

yhtppp的专栏 1万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SystemUI_Recents界面滑动偶尔卡住不动

故事是这样事儿的: 刚入职不久,leader就分给我一个bug让我研究研究。 Bug:查看最近任务时,有时上滑或下滑的时候,tp有报点,但应用界面未执行响应动画。 当时对SystemUI不怎么了解,看了bug后一脸懵逼。 过了两天,leader又来消息啦,没什么思路的话就提MTK EService吧。一阵喜悦涌上心头,这个我会啊!几分钟操作,case提交成功。没想到,故事才刚刚开始。MTK 沟通了...

思念叨火车的专栏 820

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android系统Launcher的启动流程源代码分析

在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Launcher应用程序的启动过程。 Android系统的Home应用程序Launcher是由ActivityManagerService启动的,而ActivityManagerService和PackageManagerService一样,都是在开机时由Syste

CallmeZhe的博客 664

AndroidQ 分屏窗口模式 (AMS部分)

1. 多窗口 1.1 栈 Android7.0开始支持多窗口,多窗口分为三种,画中画,分屏,自有窗口,多窗口的核心原理其实就是分栈和设置栈边界, 分栈即把不同窗口模式下的Activity放在不同的ActivityStack中,Android7.0为区分不同ActivityStack定义了不同stackId: /** First static stack ID. */ public static final int FIRST_STATIC_STACK_ID = 0;

qq_34211365的博客 1万+

Android远程过渡动画

Android的系统动画我分为三类:窗口动画,过渡动画,旋转动画。而这篇文章将分析过渡动画。而过渡动画根据创建leash和运行动画是否在同一个进程可以分为本地过渡动画和远程过渡动画,启动远程过渡动画流程相比于其他系统动画的过程,因为涉及到了跨进程,所以涉及到的过程还是比较复杂的,这篇文章将基于Android13分析远程过渡动画。

qq_41095045的博客 4894

高通Android 12/13 Launcher3修改RecentView与屏幕方向保持一致

最近同事遇到一个需求说,recentview应用预览与屏幕方向不一致,问题,于是加了一些日志,实现此需求。3、最后展示RecentView与屏幕方向保持一致。2、源码修改diff如下所示。源码修改路径汇总如下。

郑敏 1244

Android Recentsview多任务界面,taskview黑屏原因

recentsview下出现taskview黑屏问题

raolulu的博客 893
上一篇: Pip小窗模式到全屏模式源码分析-android framework车载车机手机系统开发
下一篇: android T 分屏流程之systemui部分/android framework车载车机手机实战开发
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值