背景:

今年车展上,网友蚱蜢同学带回来了一些车载rom相关的一些素材,刚好也发布了wms/ams专题课程,有粉丝朋友提供了一个车机的双屏互动的产品交互视频如下:

上面的就是车机两个屏幕的互动联动情况,转化成设计图如下:

需求说明

这里对在个双屏需求进行要点细分:
1、通过多手指对屏幕1画面A进行拖动滑动

2、画面A可以跟随手指进行平移,即有跟手功能

3、拖到一定阈值时候松手,画面A会自动动画移动到屏幕2

4、拖动和动画过程画面A依旧是可以刷新的,不是截图

5、在没有达到滑动屏幕2阈值,则需要对画面进行动画返回原来屏幕1的原来位置

上面4个要点就是实现的核心部分,主要难度在以下几个方面:
1、多指全局动作监听,而不是在某个app的onTouch里面监听,这里其实之前的input专题课程是有讲解的
所以这里部分基本上学员都可以搞定

2、画面A的平移,两个屏幕都要进行显示,这个难度较大,得考虑好相关的画面怎么都可以显示在两个屏幕

3、画面A移动过程也可以进行刷新,这个相对截图画面A进行显示难度可能又大一些

4、移动后整个画面A就完全在屏幕2了

需求实现

看完需求,大概也就知道本质就是通过在屏幕1上面多指触摸画面A,然后画面A可以到达屏幕2

那么先不考虑动画体验相关,如果只实现一个最简单版本的双屏移动,哈哈,其实这个车展上也有的车厂就是这样实现的:

这个就是没有动画版本的双屏互动,功能其实也是实现的,但是体验是不是感觉起来差的太多,而且还带有黑屏。。。
不过还好的是功能可以用,那么我们也根据wms课程基础后也来实现一下这个双屏互动的功能。

1、背景知识-wms的层级结构树
移动的画面A,其实一般就是我们Activity,一般在一个task中

task一般是挂载在某个displaycontent下的TaskDisplayArea下面,具体如下图所示

那么系统中有没有现成的方法就可以吧Task从这个display1移动到对应的diplay2下面呢?

答案当然是有的,方法就是RootWindowContainer里面的

/*** Move root task with all its existing content to specified display.** @param rootTaskId Id of root task to move.* @param displayId  Id of display to move root task to.* @param onTop      Indicates whether container should be place on top or on bottom.*/void moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop) {final DisplayContent displayContent = getDisplayContentOrCreate(displayId);if (displayContent == null) {throw new IllegalArgumentException("moveRootTaskToDisplay: Unknown displayId="+ displayId);}moveRootTaskToTaskDisplayArea(rootTaskId, displayContent.getDefaultTaskDisplayArea(),onTop);}/*** Move root task with all its existing content to specified task display area.** @param rootTaskId      Id of root task to move.* @param taskDisplayArea The task display area to move root task to.* @param onTop           Indicates whether container should be place on top or on bottom.*/void moveRootTaskToTaskDisplayArea(int rootTaskId, TaskDisplayArea taskDisplayArea,boolean onTop) {final Task rootTask = getRootTask(rootTaskId);if (rootTask == null) {throw new IllegalArgumentException("moveRootTaskToTaskDisplayArea: Unknown rootTaskId="+ rootTaskId);}final TaskDisplayArea currentTaskDisplayArea = rootTask.getDisplayArea();if (currentTaskDisplayArea == null) {throw new IllegalStateException("moveRootTaskToTaskDisplayArea: rootTask=" + rootTask+ " is not attached to any task display area.");}if (taskDisplayArea == null) {throw new IllegalArgumentException("moveRootTaskToTaskDisplayArea: Unknown taskDisplayArea=" + taskDisplayArea);}if (currentTaskDisplayArea == taskDisplayArea) {throw new IllegalArgumentException("Trying to move rootTask=" + rootTask+ " to its current taskDisplayArea=" + taskDisplayArea);}rootTask.reparent(taskDisplayArea, onTop);//这里就是核心,把task重新挂载到了新display的taskDisplayArea// Resume focusable root task after reparenting to another display area.rootTask.resumeNextFocusAfterReparent();// TODO(multi-display): resize rootTasks properly if moved from split-screen.}

其实实现也很简单,就是吧task容器重新挂载到新的display的TaskDisplayArea

下面来实际调用一下这个方法的实际效果:
这里其实不需要写代码,可以直接调用am display相关的命令即可以实现这个方法的调用。
可以用am -h看看相关的命令帮助提示,有一个display参数:

  display [COMMAND] [...]: sub-commands for operating on displays.move-stack <STACK_ID> <DISPLAY_ID>Move <STACK_ID> from its current display to <DISPLAY_ID>.

使用方式就是:
am display move-stack taskid displayId

那么这里的taskid就是activity所在roottask的id,我们可以通过am stack list看到:

255|emulator_x86_64:/ # am stack list
RootTask id=420 bounds=[0,0][1440,2960] displayId=0 userId=0configuration={1.0 310mcc260mnc [en_US] ldltr sw411dp w411dp h797dp 560dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1440, 2960) mAppBounds=Rect(0, 0 - 1440, 2876) mMaxBounds=Rect(0, 0 - 1440, 2960) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_0}-455144485 s.24 fontWeightAdjustment=0}taskId=420: com.android.gallery3d/com.android.gallery3d.app.GalleryActivity bounds=[0,0][1440,2960] userId=0 visible=true topActivity=ComponentInfo{com.android.gallery3d/com.android.gallery3d.app.GalleryActivity}RootTask id=1 bounds=[0,0][1440,2960] displayId=0 userId=0configuration={1.0 310mcc260mnc [en_US] ldltr sw411dp w411dp h797dp 560dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1440, 2960) mAppBounds=Rect(0, 0 - 1440, 2876) mMaxBounds=Rect(0, 0 - 1440, 2960) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0}-454220964 s.24 fontWeightAdjustment=0}taskId=419: com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher bounds=[0,0][1440,2960] userId=0 visible=false topActivity=ComponentInfo{com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}RootTask id=3 bounds=[0,0][1440,2960] displayId=0 userId=0configuration={1.0 310mcc260mnc [en_US] ldltr sw411dp w411dp h797dp 560dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1440, 2960) mAppBounds=Rect(0, 0 - 1440, 2876) mMaxBounds=Rect(0, 0 - 1440, 2960) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0}-456068006 s.24 fontWeightAdjustment=0}taskId=3: unknown bounds=[0,0][1440,2960] userId=0 visible=falseRootTask id=4 bounds=[0,0][1440,2960] displayId=0 userId=0configuration={1.0 310mcc260mnc [en_US] ldltr sw411dp w411dp h797dp 560dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1440, 2960) mAppBounds=Rect(0, 0 - 1440, 2876) mMaxBounds=Rect(0, 0 - 1440, 2960) mDisplayRotation=ROTATION_0 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0}-456068006 s.24 fontWeightAdjustment=0}taskId=5: unknown bounds=[0,0][1440,2960] userId=0 visible=falsetaskId=6: unknown bounds=[0,0][1440,2960] userId=0 visible=false

可以看出com.android.gallery3d/com.android.gallery3d.app.GalleryActivity这Activity的对应RootTask id为:
RootTask id=420

dipslayId那就是屏幕的id,这个也可以通过如下命令获取:

test@test:~/Downloads$ adb shell dumpsys display | grep mDisplayId
adb server version (41) doesn't match this client (39); killing...
* daemon started successfullymDisplayId=0mDisplayId=2mDisplayId=0mDisplayId=2

一般默认屏幕就是0

所以这里如果要把com.android.gallery3d/com.android.gallery3d.app.GalleryActivity移动到display2命令如下:

am display move-stack 420 2

是不是明显看出来图库从屏幕1转到了屏幕2,屏幕1也有点闪黑
好,那我们下一节再进行具体代码实现,进行手势触摸实现
ps:需要相关代码和资料请加入下面微信公众号哈

千里马android framework车机车载手机智能驾驶双屏互动实现方案相关推荐

  1. 千里马android framework开发解决Accessing hidden method限制,让应用访问隐藏方法(需要可以修改系统源码方案)

    hi,粉丝朋友们大家好! 今天来给大家分享一下,就是经常大家会做安卓系统开发工作问到一个问题,那就是我如果framework代码中增加了一个方法啥的,但是我又不想公开给第三方应用知道,只想让我系统的应 ...

  2. 华为不造车,广汽合作智能驾驶

    华为不造车,广汽合作智能驾驶 2021年5月21日,华为再度发布声明重申华为不造车.华为公司表示,这一长期战略在2018年就已明确,没有任何改变."华为表示,至今为止并未投资任何车企.未来也 ...

  3. 近期活动盘点:车路协同与智能驾驶思享会(1.22)

    想知道近期有什么最新活动?大数点为你整理的近期活动信息在此: 车路协同与智能驾驶思享会 2019年1月22日 智能车路协同技术是当今国际智能交通领域的前沿技术和必然发展趋势,是提高效率.优化能耗.降低 ...

  4. 智能驾驶域控制器硬件方案演进趋势分析

    交流群 | 进"传感器群/滑板底盘群"请加微信号:xsh041388 交流群 | 进"域控制器群/操作系统群"请加微信号:ckc1087 备注信息:传感器/滑板 ...

  5. 手握14万,博越是最佳选?这车配钢炮动力,可双屏互动,不香?

    据数据统计,中国汽车市场中,首次购车的消费者预算平均值为14万,而大家在选择家用车时,大多倾向于选择同价位的SUV车型,因为SUV通过性更强,过沟沟坎坎更方便,乘坐/后备箱的空间也会更大.而在14万左 ...

  6. 高通再次「押宝」中科创达,挑战智能驾驶软硬件全栈方案

    随着英伟达.地平线在中国市场刮起智能驾驶计算平台的「市场替代战」,作为后来者的高通,也坐不住了.这家全球移动芯片巨头此前在中国市场仅拿到了长城的智能驾驶定点. 目前,英伟达在中国市场已经拿到了蔚来.理 ...

  7. 智能驾驶功能安全综合方案

    结合自身汽车电子产品研发实践,经纬恒润功能安全团队在智驾域提供覆盖安全流程.产品开发认证及工具平台的综合解决方案. 智驾功能安全流程搭建 智驾功能安全产品开发及认证 通过功能安全模板.开发实例及定制的 ...

  8. 千里马 android framework之MotionEvent.ACTION_CANCEL怎么产生-讨厌的android触摸面试题

    hi,粉丝朋友! 大家对于MotionEvent.ACTION_CANCEL这个cancel事件是不是感觉又熟悉又陌生,熟悉是因为经常在onTouch识别触摸事件时候会把它和ACTION_UP放在一块 ...

  9. 华为被上汽狂DISS:智能驾驶时代车企呼唤“主权”?

    文|螳螂财经 作者|宁然野 智能驾驶领域的"新兵"华为,最近遇到了一件颇不被给面子的事. 近日的上汽集团2020年年度股东大会,董事长陈虹亲自作答,而当有股民问及上汽是否考虑与华为 ...

最新文章

  1. 如何查找僵尸进程并Kill之,杀不掉的要查看父进程并杀之
  2. MacOS无法登录App Store修复
  3. js 预编译 解释执行 作用域链 闭包
  4. 结构化程序goto语句_C ++ goto语句| 查找输出程序| 套装1
  5. 使用CSS3改变文本选中的默认颜色
  6. Html跳转页面时,URL传值-获取
  7. 【微信公众号开发系列文章】一、微信公众号开发环境搭建
  8. 大数据驱动教育变革,产教融合呈现新高度——数据科学与大数据技术教育分论坛顺利召开...
  9. inpur标签的各种type
  10. 技术管理之巅-如何从零打造高质效互联网技术团队?
  11. 如何写一份优秀的投资计划书
  12. 【Redis】客户端RedisClient
  13. 学习安卓的简单心得,以及LinearLayout的简单使用
  14. php开源论坛系统,十款开源论坛系统推荐(二)
  15. 未压缩视频数据计算方式
  16. 中国发射的世界首颗量子卫星“墨子号”,到底是干什么用的?
  17. 9.0以下免root框架,免 root 框架
  18. 香橙派(Orange Pi)树莓派开发板USBCAN适配器usb转can调试软件使用教程
  19. Linux网卡驱动(1)-网卡驱动架构分析
  20. 如何用人工智能免费抠除任意视频背景?

热门文章

  1. matlab基本矩阵运算,MATLAB入门:基本操作与矩阵运算
  2. 安装navicat详细流程
  3. 物化实验计算机量子化学计算,量子化学计算实验详解.pdf
  4. Linux内核SCSI子系统(1)基本介绍
  5. 期货反向跟单--与趋势策略对比
  6. ubuntu20.04安装tensorflow2.4,安装过程中出现了ERROR: Could not find a version that satisfies the requirement...
  7. 极客日报:达摩院实现全球最大AI预训练模型;苹果3nm芯片或将2023年问世;微软官宣加入JCP计划
  8. 施一公 如何提高英文的科研写作能力
  9. python 绘制3D散点图
  10. 如果串口驱动有问题,怎么调