android 11添加切换分屏功能

android 11添加切换分屏功能

引言

自Android 7开始官方就支持分屏显示,但没有切换分屏的功能,即交换上下屏幕。直到Android 13开始才支持切换分屏,操作方式是:分屏模式下双击中间分割线就会交换上下屏位置。本文的目的就是在Android 11上实现切换分屏的功能。

下图是Android13切换分屏演示

切换分屏原理说明

systemui启动后就会创建属于分屏模式的两个任务栈,一个StackId=3且mode=split-screen-primary表示上半屏任务栈,显示位置为bounds=[0,0][720,606],一个StackId=4且mode=split-screen-secondary表示下半屏任务栈,显示位置为bounds=[0,626][720,1280]。 要交换上下屏显示,只需要修改下两个任务栈(即bounds)的显示位置即可,修改方式通过修改任务栈关联的SurfaceControl的position和bounds。

修改实现

因为Android13和Android14切换分屏操作是双击中间的分割线,因此我们参看他们的也实现同样的功能。 我这里有android14的代码,我们来看看android14的关键部分:

android14双击分屏分割线代码调用路径

DoubleTapListener.onDoubleTap(MotionEvent e)

mSplitLayout.onDoubleTappedDivider()

mSplitLayoutHandler.onDoubleTappedDivider()

switchSplitPosition("double tap")

switchSplitPosition方法在StageCoordinator.java类里 实现分屏交换的就是红框里的方法。

关键地方找到了就好办了,下面是我在android11上的修改,主要的修改类:

frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java

修改如下:

diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java

index b6c6afd523b3..981bab3263e4 100644

--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java

+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java

@@ -25,7 +25,10 @@ import android.animation.Animator;

import android.animation.AnimatorListenerAdapter;

import android.animation.ValueAnimator;

import android.annotation.Nullable;

+import android.content.BroadcastReceiver;

import android.content.Context;

+import android.content.Intent;

+import android.content.IntentFilter;

import android.content.res.Configuration;

import android.graphics.Matrix;

import android.graphics.Rect;

@@ -36,8 +39,10 @@ import android.os.Bundle;

import android.os.Handler;

import android.os.RemoteException;

import android.util.AttributeSet;

+import android.util.Log;

import android.util.Slog;

import android.view.Display;

+import android.view.GestureDetector;

import android.view.MotionEvent;

import android.view.PointerIcon;

import android.view.SurfaceControl;

@@ -55,6 +60,8 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;

import android.view.animation.Interpolator;

import android.view.animation.PathInterpolator;

import android.widget.FrameLayout;

+import android.window.WindowContainerTransaction;

+import android.window.WindowOrganizer;

import com.android.internal.graphics.SfVsyncFrameCallbackProvider;

import com.android.internal.logging.MetricsLogger;

@@ -77,6 +84,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,

OnComputeInternalInsetsListener {

private static final String TAG = "DividerView";

private static final boolean DEBUG = Divider.DEBUG;

+ private GestureDetector mDoubleTapDetector;

+ boolean mToggleSplitScreen;

public interface DividerCallbacks {

void onDraggingStart();

@@ -175,6 +184,16 @@ public class DividerView extends FrameLayout implements OnTouchListener,

private final Handler mHandler = new Handler();

+ private static final String ACTION_TOGGLE_SPLIT_SCREEN = "action_toggle_split_screen";

+ private BroadcastReceiver mToggleSplitScreenReceiver = new BroadcastReceiver() {

+ @Override

+ public void onReceive(Context context, Intent intent) {

+ if (intent.getAction().equals(ACTION_TOGGLE_SPLIT_SCREEN)){

+ toggleSplitScreen("receive toggle_split_screen broadcast");

+ }

+ }

+ };

相关推荐