多屏联动 - 动画

基于Android R版本分析

参考:车载多屏互动联动动画版本同屏幕大小情况方案设计

实现双屏联动的效果,需要关注两个部分:

  • 手势识别;
  • move stack进行移栈操作;

手势识别

基于原生手指识别的基础上,我们新定义自信的手指识别,例如:在3指滑动的情况下,实现Task move的操作;

实现方案

  • 单独创建一个PointerEventListener的实现类,该实现类用于处理3指滑动的逻辑;
  • 将该监听注册到DisplayContent中,这样每一个DisplayId都会对应一个PointerEventListener,每一个屏幕都可以响应3指滑动;

核心点

  • 当前场景是否处于3指滑动, 针对非3指滑动场景下也需要进行处理;

  • MotionEvent.ACTION_DOWN、MotionEvent.ACTION_POINTER_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_POINTER_UP、MotionEvent.ACTION_UP 5个Event的响应;

  • 开启move stack的临界值判断,例如:滑动间距 >= 10px时,触发move stack;

  • 结束3指滑动之后,Task自动move的临界值判断,例如:

    • 当move 间隔 >= 100px时,Task向右侧/左侧滑动,代表move stack成功;
    • 当move 间隔 < 100px时,Task向右侧/左侧滑动,代表move stack未成功,Task自动回位;
  • 主副屏的判断(默认主屏在 ,副屏在),例如:

    • 主屏Task向副屏滑动时,主屏Task不能向左滑动,滑动过程中也不允许主屏Task向左滑动;
    • 副屏Task向主屏滑动时,主屏Task不能向右滑动,滑动过程中也不允许副屏Task向右滑动;

move stack

移栈的操作,最核心的逻辑就是move stack,该接口的版本迭代:

  • Android O 提供了moveStackToDisplay能力,在DisplayContent中实现;
  • Android O ~ Android Q,该接口一致又DisplayContent提供;
  • Android R开始,新增了RootWindowContainer类,moveStackToDisplay接口移植到RootWindowContainer中实现;
  • Android S 开始,该接口名称修改为了moveRootTaskToDisplayAndroid T沿用moveRootTaskToDisplay;
核心点

在Android R版本中使用时,需要对比Android S ~ Android T的moveRootTaskToDisplay接口逻辑,各版本之间的实现逻辑上有一点的差异性;

双屏双图层

我们知道,在启动应用的时候,不会启动多个相同的应用进程,即无论存在多少个屏幕,同一个应用进程只会启动一个;那么对应的Task要不在Display 0显示,要不在Display 1中显示,无法做到两个屏幕同时显示同一个应用进程;

需要解决Display 0和Display 1同时显示Task画面;

实现方案

Android R 及之后,在SurfaceControl提供了mirrorSurface接口:

java 复制代码
/**
  * Creates a mirrored hierarchy for the mirrorOf {@link SurfaceControl}
  *
  * Real Hierarchy    Mirror
  *                     SC (value that's returned)
  *                      |
  *      A               A'
  *      |               |
  *      B               B'
  *
  * @param mirrorOf The root of the hierarchy that should be mirrored.
  * @return A SurfaceControl that's the parent of the root of the mirrored hierarchy.
  *
  * @hide
  */
public static SurfaceControl mirrorSurface(SurfaceControl mirrorOf) {
    long nativeObj = nativeMirrorSurface(mirrorOf.mNativeObject);
    SurfaceControl sc = new SurfaceControl();
    sc.assignNativeObject(nativeObj, "mirrorSurface");
    return sc;
}

Animator move

动画滑动的效果,本质上就是Task的偏移;

实现方案

滑动动画的实现方案:Matrix + SurfaceControl.Transaction

Matrix是Android中一个重要的类,提供了一些矩阵变换的方法,可以实现图形的缩放、旋转、平移和倾斜等操作;

start move

Display 0画面移动情况:

  • Display 0是接受了3指触摸的右边移动了offsetX的距离,这时候屏幕Display 0的Task画面也要跟着向右平移offsetX;

Display 1画面移动情况:

  • Display 1的Task画面应该最右边往左边有offsetX的画面,所以左边原点相对屏幕偏移距离就应该是 -(width - offsetX),这里应该是负数,因为屏幕最左边才是0;
Auto move

PointerEvent结束之后,Task画面并不是已经完全移动到另一个人屏幕中,Task画面大概念横跨两个屏幕,这样就需要判断Task auto move的临界值;

总结

在实现过程中,需要关注的几个点:

  • 在move主屏的Task至副屏之后,主屏/副屏的界面实现不能为黑屏状态;
  • 针对不同屏幕分辨率的时候,需要新增Scale操作;
  • 针对不同屏幕density的时候,需要考虑解决方案;
  • 在移栈的时候,有可能会出现黑屏闪烁的情况,这个问题需要调研(Activity重建导致的);

针对size和density不一致问题,需要在应用模块AndroidManifest.xml中新增属性:

ini 复制代码
android:configChanges="density|screenSize|smallestScreenSize"
  • density:像素密度
  • screenSize:屏幕大小
  • smallestScreenSize:屏幕的物理大小改变(可选)
相关推荐
子非衣3 小时前
MySQL修改JSON格式数据示例
android·mysql·json
网络安全(king)6 小时前
网络安全知识:网络安全网格架构
安全·web安全·架构
openinstall全渠道统计6 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
双鱼大猫7 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫7 小时前
一句话说透Android里面的查找服务
android
双鱼大猫7 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫7 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫8 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫8 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫8 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android