From 0f6526e0c43864cbf4000b89ccd36744f77c93f6 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Tue, 11 Oct 2022 16:59:05 -0700 Subject: [PATCH] Improve TaskMenuView layouts for split pairs * Instead of basing calculations on the TaskView view, use the TaskThumbnailView as the anchor. This helps us prevent having to re-calculate positions that were already done to layout the thumbnails * TODO: Gracefully handle re-positioning task menu view on rotation Bug: 249693334 Test: Manual, opening task menu view in land/seascape in portrait, w/ and w/o home rotation Change-Id: I02da96d2735657d5340e23056de69392ff8452c4 --- .../quickstep/views/GroupedTaskView.java | 17 ----- .../android/quickstep/views/TaskMenuView.java | 65 ++++++------------- .../touch/LandscapePagedViewHandler.java | 53 ++++++--------- .../touch/PagedOrientationHandler.java | 27 ++------ .../touch/PortraitPagedViewHandler.java | 53 ++++----------- .../touch/SeascapePagedViewHandler.java | 32 ++++----- 6 files changed, 72 insertions(+), 175 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 3a5f606467..967814accb 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -1,6 +1,5 @@ package com.android.quickstep.views; -import static com.android.launcher3.AbstractFloatingView.getAnyView; import static com.android.launcher3.util.SplitConfigurationOptions.DEFAULT_SPLIT_RATIO; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; @@ -14,7 +13,6 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -164,21 +162,6 @@ public class GroupedTaskView extends TaskView { } } - @Override - protected boolean showTaskMenuWithContainer(IconView iconView) { - boolean showedTaskMenu = super.showTaskMenuWithContainer(iconView); - if (iconView == mIconView2 && showedTaskMenu && !mActivity.getDeviceProfile().isTablet) { - // Adjust the position of the secondary task's menu view (only on phones) - TaskMenuView taskMenuView = getAnyView(mActivity, AbstractFloatingView.TYPE_TASK_MENU); - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - getRecentsView().getPagedOrientationHandler() - .setSecondaryTaskMenuPosition(mSplitBoundsConfig, this, - deviceProfile, mTaskIdAttributeContainer[0].getThumbnailView(), - taskMenuView); - } - return showedTaskMenu; - } - @Nullable @Override public RunnableList launchTaskAnimated() { diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index 681574573e..2c9afb4b4c 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -23,7 +23,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Outline; -import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RectShape; @@ -32,7 +31,6 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewOutlineProvider; -import android.view.ViewTreeObserver.OnScrollChangedListener; import android.widget.LinearLayout; import android.widget.TextView; @@ -56,13 +54,12 @@ import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; /** * Contains options for a recent task when long-pressing its icon. */ -public class TaskMenuView extends AbstractFloatingView implements OnScrollChangedListener { +public class TaskMenuView extends AbstractFloatingView { private static final Rect sTempRect = new Rect(); private static final int REVEAL_OPEN_DURATION = 150; private static final int REVEAL_CLOSE_DURATION = 100; - private final float mTaskInsetMargin; private BaseDraggingActivity mActivity; private TextView mTaskName; @@ -81,7 +78,6 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange mActivity = BaseDraggingActivity.fromContext(context); setClipToOutline(true); - mTaskInsetMargin = getResources().getDimension(R.dimen.task_card_margin); } @Override @@ -129,33 +125,6 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange }; } - private void setPosition(float x, float y, int overscrollShift) { - PagedOrientationHandler pagedOrientationHandler = mTaskView.getPagedOrientationHandler(); - // Inset due to margin - PointF additionalInset = pagedOrientationHandler - .getAdditionalInsetForTaskMenu(mTaskInsetMargin); - DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; - - float adjustedY = y + taskTopMargin - additionalInset.y; - float adjustedX = x - additionalInset.x; - // Changing pivot to make computations easier - // NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set, - // which would render the X and Y position set here incorrect - setPivotX(0); - if (deviceProfile.isTablet) { - // In tablet, set pivotY to original position without mThumbnailTopMargin adjustment. - setPivotY(-taskTopMargin); - } else { - setPivotY(0); - } - setRotation(pagedOrientationHandler.getDegreesRotated()); - setX(pagedOrientationHandler.getTaskMenuX(adjustedX, - mTaskContainer.getThumbnailView(), overscrollShift, deviceProfile)); - setY(pagedOrientationHandler.getTaskMenuY( - adjustedY, mTaskContainer.getThumbnailView(), overscrollShift)); - } - public void onRotationChanged() { if (mOpenCloseAnimator != null && mOpenCloseAnimator.isRunning()) { mOpenCloseAnimator.end(); @@ -187,17 +156,9 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange return false; } post(this::animateOpen); - ((RecentsView) mActivity.getOverviewPanel()).addOnScrollChangedListener(this); return true; } - @Override - public void onScrollChanged() { - RecentsView rv = mActivity.getOverviewPanel(); - setPosition(mTaskView.getX() - rv.getScrollX(), mTaskView.getY() - rv.getScrollY(), - rv.getOverScrollShift()); - } - /** @return true if successfully able to populate task view menu, false otherwise */ private boolean populateAndLayoutMenu() { if (mTaskContainer.getTask().icon == null) { @@ -234,18 +195,18 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange RecentsView recentsView = mActivity.getOverviewPanel(); PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler(); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); - orientationHandler.setTaskMenuAroundTaskView(this, mTaskInsetMargin); // Get Position DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - mActivity.getDragLayer().getDescendantRectRelativeToSelf(mTaskView, sTempRect); + mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskContainer.getThumbnailView(), + sTempRect); Rect insets = mActivity.getDragLayer().getInsets(); BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams(); int padding = getResources() .getDimensionPixelSize(R.dimen.task_menu_vertical_padding); params.width = orientationHandler .getTaskMenuWidth(taskContainer.getThumbnailView(), - deviceProfile) - (2 * padding); + deviceProfile, taskContainer.getStagePosition()) - (2 * padding); // Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start params.gravity = Gravity.LEFT; setLayoutParams(params); @@ -260,7 +221,22 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange orientationHandler.setTaskOptionsMenuLayoutOrientation( deviceProfile, mOptionLayout, dividerSpacing, divider); - setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top, 0); + float thumbnailAlignedX = sTempRect.left - insets.left; + float thumbnailAlignedY = sTempRect.top - insets.top; + // Changing pivot to make computations easier + // NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set, + // which would render the X and Y position set here incorrect + setPivotX(0); + setPivotY(0); + setRotation(orientationHandler.getDegreesRotated()); + + // Margin that insets the menuView inside the taskView + float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin); + setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX, + mTaskContainer.getThumbnailView(), deviceProfile, taskInsetMargin)); + setTranslationY(orientationHandler.getTaskMenuY( + thumbnailAlignedY, mTaskContainer.getThumbnailView(), + mTaskContainer.getStagePosition(), this, taskInsetMargin)); } private void animateOpen() { @@ -306,7 +282,6 @@ public class TaskMenuView extends AbstractFloatingView implements OnScrollChange private void closeComplete() { mIsOpen = false; mActivity.getDragLayer().removeView(this); - ((RecentsView) mActivity.getOverviewPanel()).removeOnScrollChangedListener(this); } private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider() { diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index ceebc2e168..155ecf3581 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -30,6 +30,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN; import android.content.res.Resources; @@ -265,20 +266,32 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { } @Override - public float getTaskMenuX(float x, View thumbnailView, int overScroll, - DeviceProfile deviceProfile) { - return thumbnailView.getMeasuredWidth() + x; + public float getTaskMenuX(float x, View thumbnailView, + DeviceProfile deviceProfile, float taskInsetMargin) { + return thumbnailView.getMeasuredWidth() + x - taskInsetMargin; } @Override - public float getTaskMenuY(float y, View thumbnailView, int overScroll) { - return y + overScroll + - (thumbnailView.getMeasuredHeight() - thumbnailView.getMeasuredWidth()) / 2f; + public float getTaskMenuY(float y, View thumbnailView, int stagePosition, + View taskMenuView, float taskInsetMargin) { + BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams(); + int taskMenuWidth = lp.width; + if (stagePosition == STAGE_POSITION_UNDEFINED) { + return y + taskInsetMargin + + (thumbnailView.getMeasuredHeight() - taskMenuWidth) / 2f; + } else { + return y + taskInsetMargin; + } } @Override - public int getTaskMenuWidth(View view, DeviceProfile deviceProfile) { - return view.getMeasuredWidth(); + public int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, + @StagePosition int stagePosition) { + if (stagePosition == SplitConfigurationOptions.STAGE_POSITION_UNDEFINED) { + return thumbnailView.getMeasuredWidth(); + } else { + return thumbnailView.getMeasuredHeight(); + } } @Override @@ -299,17 +312,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { lp.height = WRAP_CONTENT; } - @Override - public void setTaskMenuAroundTaskView(LinearLayout taskView, float margin) { - BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskView.getLayoutParams(); - lp.topMargin += margin; - } - - @Override - public PointF getAdditionalInsetForTaskMenu(float margin) { - return new PointF(margin, 0); - } - @Override public Pair getDwbLayoutTranslations(int taskViewWidth, int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile, @@ -376,19 +378,6 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { return isRtl ? 1 : -1; } - @Override - public void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView, - DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView) { - float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically - ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent) - : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent); - FrameLayout.LayoutParams snapshotParams = - (FrameLayout.LayoutParams) primarySnaphotView.getLayoutParams(); - float additionalOffset = (taskView.getHeight() - snapshotParams.topMargin) - * topLeftTaskPlusDividerPercent; - taskMenuView.setY(taskMenuView.getY() + additionalOffset); - } - /* -------------------- */ @Override diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index cbcb70013a..623446288f 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -184,9 +184,12 @@ public interface PagedOrientationHandler { * taskMenu width is the same size as the thumbnail width (what got set below in * getTaskMenuWidth()), so we directly use that in the calculations. */ - float getTaskMenuX(float x, View thumbnailView, int overScroll, DeviceProfile deviceProfile); - float getTaskMenuY(float y, View thumbnailView, int overScroll); - int getTaskMenuWidth(View view, DeviceProfile deviceProfile); + float getTaskMenuX(float x, View thumbnailView, DeviceProfile deviceProfile, + float taskInsetMargin); + float getTaskMenuY(float y, View thumbnailView, int stagePosition, + View taskMenuView, float taskInsetMargin); + int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, + @StagePosition int stagePosition); /** * Sets linear layout orientation for {@link com.android.launcher3.popup.SystemShortcut} items * inside task menu view. @@ -200,16 +203,6 @@ public interface PagedOrientationHandler { */ void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp, LinearLayout viewGroup, DeviceProfile deviceProfile); - /** - * Adjusts margins for the entire task menu view itself, which comprises of both app title and - * shortcut options. - */ - void setTaskMenuAroundTaskView(LinearLayout taskView, float margin); - /** - * Since the task menu layout is manually positioned on top of recents view, this method returns - * additional adjustments to the positioning based on fake land/seascape - */ - PointF getAdditionalInsetForTaskMenu(float margin); /** * Calculates the position where a Digital Wellbeing Banner should be placed on its parent @@ -230,14 +223,6 @@ public interface PagedOrientationHandler { /** @return Either 1 or -1, a factor to multiply by so the animation goes the correct way. */ int getTaskDragDisplacementFactor(boolean isRtl); - /** - * Calls the corresponding {@link View#setX(float)} or {@link View#setY(float)} - * on {@param taskMenuView} by taking the space needed by {@param primarySnapshotView} into - * account. - * This is expected to only be called for secondary (bottom/right) tasks. - */ - void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView, - DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView); /** * Maps the velocity from the coordinate plane of the foreground app to that * of Launcher's (which now will always be portrait) diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index a9ae7dc4bd..f4ba76e3f9 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -55,7 +55,6 @@ import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; -import com.android.launcher3.views.BaseDragLayer; import java.util.List; @@ -264,26 +263,28 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } @Override - public float getTaskMenuX(float x, View thumbnailView, int overScroll, - DeviceProfile deviceProfile) { + public float getTaskMenuX(float x, View thumbnailView, + DeviceProfile deviceProfile, float taskInsetMargin) { if (deviceProfile.isLandscape) { - return x + overScroll + return x + taskInsetMargin + (thumbnailView.getMeasuredWidth() - thumbnailView.getMeasuredHeight()) / 2f; } else { - return x + overScroll; + return x + taskInsetMargin; } } @Override - public float getTaskMenuY(float y, View thumbnailView, int overScroll) { - return y; + public float getTaskMenuY(float y, View thumbnailView, int stagePosition, + View taskMenuView, float taskInsetMargin) { + return y + taskInsetMargin; } @Override - public int getTaskMenuWidth(View view, DeviceProfile deviceProfile) { + public int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, + @StagePosition int stagePosition) { return deviceProfile.isLandscape && !deviceProfile.isTablet - ? view.getMeasuredHeight() - : view.getMeasuredWidth(); + ? thumbnailView.getMeasuredHeight() + : thumbnailView.getMeasuredWidth(); } @Override @@ -303,38 +304,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { lp.height = WRAP_CONTENT; } - @Override - public void setTaskMenuAroundTaskView(LinearLayout taskView, float margin) { - BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskView.getLayoutParams(); - lp.topMargin += margin; - lp.leftMargin += margin; - } - - @Override - public PointF getAdditionalInsetForTaskMenu(float margin) { - return new PointF(0, 0); - } - - @Override - public void setSecondaryTaskMenuPosition(SplitBounds splitBounds, View taskView, - DeviceProfile deviceProfile, View primarySnaphotView, View taskMenuView) { - float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically - ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent) - : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent); - FrameLayout.LayoutParams snapshotParams = - (FrameLayout.LayoutParams) primarySnaphotView.getLayoutParams(); - float additionalOffset; - if (deviceProfile.isLandscape) { - additionalOffset = (taskView.getWidth() - snapshotParams.leftMargin) - * topLeftTaskPlusDividerPercent; - taskMenuView.setX(taskMenuView.getX() + additionalOffset); - } else { - additionalOffset = (taskView.getHeight() - snapshotParams.topMargin) - * topLeftTaskPlusDividerPercent; - taskMenuView.setY(taskMenuView.getY() + additionalOffset); - } - } - @Override public Pair getDwbLayoutTranslations(int taskViewWidth, int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile, diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java index a616a8b6eb..05683bd11b 100644 --- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java @@ -24,6 +24,7 @@ import static android.view.Gravity.START; import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; +import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN; import android.content.res.Resources; @@ -33,7 +34,6 @@ import android.util.Pair; import android.view.Surface; import android.view.View; import android.widget.FrameLayout; -import android.widget.LinearLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; @@ -85,26 +85,22 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { } @Override - public float getTaskMenuX(float x, View thumbnailView, int overScroll, - DeviceProfile deviceProfile) { - return x; + public float getTaskMenuX(float x, View thumbnailView, + DeviceProfile deviceProfile, float taskInsetMargin) { + return x + taskInsetMargin; } @Override - public float getTaskMenuY(float y, View thumbnailView, int overScroll) { - return y + overScroll + - (thumbnailView.getMeasuredHeight() + thumbnailView.getMeasuredWidth()) / 2f; - } - - @Override - public void setTaskMenuAroundTaskView(LinearLayout taskView, float margin) { - BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskView.getLayoutParams(); - lp.bottomMargin += margin; - } - - @Override - public PointF getAdditionalInsetForTaskMenu(float margin) { - return new PointF(-margin, margin); + public float getTaskMenuY(float y, View thumbnailView, int stagePosition, + View taskMenuView, float taskInsetMargin) { + BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams(); + int taskMenuWidth = lp.width; + if (stagePosition == STAGE_POSITION_UNDEFINED) { + return y + taskInsetMargin + + (thumbnailView.getMeasuredHeight() + taskMenuWidth) / 2f; + } else { + return y + taskMenuWidth + taskInsetMargin; + } } @Override