多屏联动 - 非动画

基于Android R版本分析

新增 DoubleScreenMovePointerEventListener 类:

java 复制代码
package com.android.server.wm;
​
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManagerPolicyConstants;
​
public class DoubleScreenMovePointerEventListener implements WindowManagerPolicyConstants.PointerEventListener {
    private static final String TAG = DoubleScreenMovePointerEventListener.class.getName();
​
    private boolean shouldBeginMove = false;
    private int mPoint0FirstX = 0;
    private int mPoint1FirstX = 0;
    private int mPoint0LastX = 0;
    private int mPoint1LastX = 0;
    int START_GAP = 20; //动作触发阈值,最少移动为20个像素才可以
    private final WindowManagerService mService;
    private final DisplayContent mDisplayContent;
​
    public DoubleScreenMovePointerEventListener(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
        mDisplayContent = displayContent;
    }
​
    @Override
    public void onPointerEvent(MotionEvent motionEvent) {
        Log.d(TAG, "onPointerEvent: motionEvent = " + motionEvent);
        switch (motionEvent.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                if (motionEvent.getPointerCount() > 1) {
                    shouldBeginMove = false;
                    Log.d(TAG, "onPointerEvent: motionEvent.getPointerCount() > 2 end DoubleScreenMove");
                }
                if (motionEvent.getPointerCount() == 1) {
                    if (mPoint0FirstX == 0) {
                        //if (mPoint0FirstX == 0 && mPoint1FirstX == 0) {
                        mPoint0FirstX = (int) motionEvent.getX(0);
//                        mPoint1FirstX = (int) motionEvent.getX(1);
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (motionEvent.getPointerCount() == 1) {
                    if (!shouldBeginMove && (motionEvent.getX(0) - mPoint0FirstX) > START_GAP) {
                        // && (motionEvent.getX(1) - mPoint1FirstX) > START_GAP
                        //识别了双指动作达到触发task移动条件,则调用对应mDisplayContent.doTestMoveTaskToOtherDisplay方法
                        Log.d(TAG, "onPointerEvent: start DoubleScreenMove");
                        shouldBeginMove = true;
                        mDisplayContent.doMoveStackToDisplay();
                    }
                    mPoint0LastX = (int) motionEvent.getX(0);
//                    mPoint1LastX = (int) motionEvent.getX(1);
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_UP:
                shouldBeginMove = false;
                mPoint0FirstX = mPoint1FirstX = 0;
                Log.d(TAG, "onPointerEvent: ACTION_UP end DoubleScreenMove");
                break;
        }
    }
}

新增DoubleScreenMovePointerEventListener初始化(在DisplayContent中):

scss 复制代码
final DoubleScreenMovePointerEventListener mPointerEventListener;
​
DisplayContent(Display display, RootWindowContainer root) {
    ........................
    mTapDetector = new TaskTapPointerEventListener(mWmService, this);
    mPointerEventListener = new DoubleScreenMovePointerEventListener(mWmService,this);
    registerPointerEventListener(mTapDetector);
    registerPointerEventListener(mPointerEventListener);
    registerPointerEventListener(mWmService.mMousePositionTracker);
    ........................
}

修改DisplayContent,新增doMoveStackToDisplay()方法:

ini 复制代码
public void doMoveStackToDisplay() {
    DisplayContent otherDisplay = null;
    if (mRootWindowContainer.getChildCount() >= 2) {
        otherDisplay = (mRootWindowContainer.getChildAt(0) == this)
            ? mRootWindowContainer.getChildAt(1) : mRootWindowContainer.getChildAt(0);
    }
    if (otherDisplay != this && otherDisplay != null) {
        int topStackId = 0;
        try {
            Task topStack = getTopStack();
            if (topStack.isActivityTypeHome()) {
                Log.d(TAG, "doMoveStackToDisplay: isActivityTypeHome");
                return;
            }
            topStackId = topStack.mTaskId;
            mRootWindowContainer.moveStackToDisplay(topStackId, otherDisplay.mDisplayId, true);
        } catch (Exception ex) {
            Log.d(TAG, "doMoveStackToDisplay: exception = " + ex);
        }
    }
}

参考:blog.csdn.net/learnframew...

相关推荐
_龙小鱼_1 小时前
卡顿检测与 Choreographer 原理
android·kotlin
云手机管家2 小时前
账号风控突破:云手机设备指纹篡改检测与反制技术解析
android·运维·网络协议·网络安全·智能手机·矩阵·自动化
千里马-horse2 小时前
Detected for tasks ‘compileDebugJavaWithJavac‘ (17) and ‘kspDebugKotlin‘ (21).
android·jdk·kspdebugkotlin
柯南二号4 小时前
【Android】Android 实现一个依赖注入的注解
android
archko6 小时前
语音识别-3,添加ai问答
android·人工智能
奔跑吧 android12 小时前
【android bluetooth 案例分析 03】【PTS 测试 】【PBAP/PCE/SGSIT/SERR/BV-01-C】
android·pts·aosp·pbap·sgsit
難釋懷15 小时前
Android开发-Application
android
MZWeiei16 小时前
Spark SQL 运行架构详解(专业解释+番茄炒蛋例子解读)
大数据·分布式·sql·架构·spark
#金毛16 小时前
一、HAL库的设计理念详解:从架构到实践
stm32·嵌入式硬件·架构
是麟渊16 小时前
【大模型面试每日一题】Day 17:解释MoE(Mixture of Experts)架构如何实现模型稀疏性,并分析其训练难点
人工智能·自然语言处理·面试·职场和发展·架构