From 43c4b50c17fa3dbdbe64938b5af9bfe4e7813569 Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Fri, 27 Oct 2023 13:14:20 +0100 Subject: [PATCH] Update Icon App Chip Menu to new specs. Fix: 304228083 Test: TaplOverviewIconAppChipMenuTest Flag: ACONFIG com.android.launcher3.enable_overview_icon_menu DEVELOPMENT Change-Id: Ib018c7f59e1141b6f21618b28d411facc937ac7c --- quickstep/res/layout/icon_app_chip_view.xml | 43 ++- quickstep/res/layout/task_menu.xml | 4 +- .../res/layout/task_view_menu_option.xml | 2 +- quickstep/res/values/dimens.xml | 43 ++- .../quickstep/views/GroupedTaskView.java | 15 +- .../quickstep/views/IconAppChipView.java | 340 ++++++++++++------ .../android/quickstep/views/RecentsView.java | 8 +- .../android/quickstep/views/TaskMenuView.java | 84 +++-- res/drawable/icon_menu_arrow_background.xml | 4 +- res/drawable/icon_menu_background.xml | 3 +- res/drawable/icon_menu_background_corners.xml | 22 ++ res/values/dimens.xml | 5 +- .../touch/LandscapePagedViewHandler.java | 83 +++-- .../touch/PagedOrientationHandler.java | 4 +- .../touch/PortraitPagedViewHandler.java | 49 +-- .../touch/SeascapePagedViewHandler.java | 59 ++- 16 files changed, 548 insertions(+), 220 deletions(-) create mode 100644 res/drawable/icon_menu_background_corners.xml diff --git a/quickstep/res/layout/icon_app_chip_view.xml b/quickstep/res/layout/icon_app_chip_view.xml index 87519a00aa..37d5eb22df 100644 --- a/quickstep/res/layout/icon_app_chip_view.xml +++ b/quickstep/res/layout/icon_app_chip_view.xml @@ -25,11 +25,23 @@ android:autoMirrored="true" android:elevation="@dimen/task_thumbnail_icon_menu_elevation" > + + + + diff --git a/quickstep/res/layout/task_menu.xml b/quickstep/res/layout/task_menu.xml index a5c944540b..622edfeba0 100644 --- a/quickstep/res/layout/task_menu.xml +++ b/quickstep/res/layout/task_menu.xml @@ -31,8 +31,8 @@ android:layout_height="match_parent" android:gravity="center" android:layout_marginBottom="2dp" - android:paddingTop="@dimen/task_menu_vertical_padding" - android:paddingBottom="@dimen/task_menu_vertical_padding" + android:paddingTop="@dimen/task_menu_edge_padding" + android:paddingBottom="@dimen/task_menu_edge_padding" android:textSize="16sp"/> diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 22f98fa422..e5eec57a65 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -44,32 +44,50 @@ 16dp 16dp - - 132dp - - 62dp - - 138dp + + 156dp 216dp + + 120dp + + 86dp + + 118dp + + 16sp + + 164dp 36dp + + 28dp + + 36dp 52dp - 32dp + 24dp 16dp - - 12dp + + 12dp + + 6dp + + 4dp + + 6dp - 6dp + 8dp 8dp 24dp + + 32dp - 36dp + 44dp 14dp 72dp @@ -113,10 +131,11 @@ 16dp - 8dp + 8dp 8dp 3dp 16dp + 18dp 10dp diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 5b1d614722..8559b37537 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -372,7 +372,20 @@ public class GroupedTaskView extends TaskView { mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx, MeasureSpec.EXACTLY)); } - updateIconPlacement(); + if (!enableOverviewIconMenu()) { + updateIconPlacement(); + return; + } + + if (getRecentsView() == null) { + return; + } + + int iconMargins = getResources().getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_start_margin) * 2; + ((IconAppChipView) mIconView).setMaxWidth(mSnapshotView.getMeasuredWidth() - iconMargins); + ((IconAppChipView) mIconView2).setMaxWidth(mSnapshotView2.getMeasuredWidth() - iconMargins); + setOrientationState(getRecentsView().getPagedViewOrientedState()); } @Override diff --git a/quickstep/src/com/android/quickstep/views/IconAppChipView.java b/quickstep/src/com/android/quickstep/views/IconAppChipView.java index 5a2e135ade..b14b917a5b 100644 --- a/quickstep/src/com/android/quickstep/views/IconAppChipView.java +++ b/quickstep/src/com/android/quickstep/views/IconAppChipView.java @@ -16,13 +16,14 @@ package com.android.quickstep.views; import static com.android.app.animation.Interpolators.EMPHASIZED; -import static com.android.launcher3.Flags.enableOverviewIconMenu; +import static com.android.app.animation.Interpolators.LINEAR; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; +import android.content.res.Resources; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; @@ -37,9 +38,8 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; -import com.android.launcher3.touch.LandscapePagedViewHandler; +import com.android.launcher3.Utilities; import com.android.launcher3.touch.PagedOrientationHandler; -import com.android.launcher3.touch.SeascapePagedViewHandler; import com.android.launcher3.views.ActivityContext; import com.android.quickstep.util.RecentsOrientedState; @@ -52,20 +52,35 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { private static final int MENU_BACKGROUND_HIDE_DURATION = 333; private IconView mIconView; - private TextView mIconTextView; + // Two textview so we can ellipsize the collapsed view and crossfade on expand to the full name. + private TextView mIconTextCollapsedView; + private TextView mIconTextExpandedView; private ImageView mIconArrowView; private ImageView mIconViewBackground; + // Use separate views for the rounded corners so we can scale the background view without + // warping the corners. + private ImageView mIconViewBackgroundCornersStart; + private ImageView mIconViewBackgroundCornersEnd; - private int mMaxIconBackgroundWidth; - private int mMinIconBackgroundWidth; - private int mMaxIconBackgroundHeight; - private int mMinIconBackgroundHeight; - private int mIconTextMinWidth; - private int mIconTextMaxWidth; - private int mInnerMargin; - private int mIconArrowSize; - private int mIconMenuMarginStart; - private int mArrowMaxTranslationX; + private final int mMinimumMenuSize; + private final int mMaxMenuWidth; + private final int mIconMenuMarginTop; + private final int mIconMenuMarginStart; + private final int mIconViewMarginStart; + private final int mIconViewDrawableSize; + private final int mIconViewDrawableMaxSize; + private final int mIconTextMinWidth; + private final int mIconTextMaxWidth; + private final int mTextMaxTranslationX; + private final int mInnerMargin; + private final float mArrowMaxTranslationX; + private final int mMinIconBackgroundWidth; + private final int mMaxIconBackgroundHeight; + private final int mMinIconBackgroundHeight; + private final int mMaxIconBackgroundCornerRadius; + private final float mMinIconBackgroundCornerRadius; + + private int mMaxWidth = Integer.MAX_VALUE; public IconAppChipView(Context context) { this(context, null); @@ -82,40 +97,66 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { public IconAppChipView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + Resources res = getResources(); - mMaxIconBackgroundWidth = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_max_width); - mMinIconBackgroundWidth = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_min_width); - mMaxIconBackgroundHeight = getResources().getDimensionPixelSize( + // Menu dimensions + mMaxMenuWidth = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_max_width); + mIconMenuMarginTop = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_top_margin); + mIconMenuMarginStart = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_start_margin); + + // Background dimensions + mMinIconBackgroundWidth = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_background_min_width); + mMaxIconBackgroundHeight = res.getDimensionPixelSize( R.dimen.task_thumbnail_icon_menu_max_height); - mMinIconBackgroundHeight = getResources().getDimensionPixelSize( + mMinIconBackgroundHeight = res.getDimensionPixelSize( R.dimen.task_thumbnail_icon_menu_min_height); - mIconTextMaxWidth = getResources().getDimensionPixelSize( + mMaxIconBackgroundCornerRadius = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_corner_radius); + + // TextView dimensions + mInnerMargin = (int) res.getDimension(R.dimen.task_thumbnail_icon_menu_arrow_margin); + mIconTextMinWidth = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_text_width); + mIconTextMaxWidth = res.getDimensionPixelSize( R.dimen.task_thumbnail_icon_menu_text_max_width); - mInnerMargin = (int) getResources().getDimension( - R.dimen.task_thumbnail_icon_menu_arrow_margin); - mIconTextMinWidth = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_text_width) + (2 * mInnerMargin); - int taskIconHeight = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_drawable_touch_size); - int arrowWidth = getResources().getDimensionPixelSize( + + // IconView dimensions + mIconViewMarginStart = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_view_start_margin); + mIconViewDrawableSize = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_drawable_size); + mIconViewDrawableMaxSize = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_drawable_max_size); + mTextMaxTranslationX = + (mIconViewDrawableMaxSize - mIconViewDrawableSize - mIconViewMarginStart) + + (mInnerMargin / 2); + + // ArrowView dimensions + int iconArrowViewWidth = res.getDimensionPixelSize( R.dimen.task_thumbnail_icon_menu_arrow_size); - mIconArrowSize = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_arrow_drawable_size); - mIconMenuMarginStart = getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_margin); - mArrowMaxTranslationX = - mMaxIconBackgroundWidth - taskIconHeight - mIconTextMaxWidth + arrowWidth; + mMinIconBackgroundCornerRadius = mMinIconBackgroundHeight / 2f; + float maxCornerSize = Math.min(mMaxIconBackgroundHeight / 2f, + mMaxIconBackgroundCornerRadius); + mArrowMaxTranslationX = (mMaxMenuWidth - maxCornerSize) - (Math.min(mMaxWidth, + mMinIconBackgroundWidth + (2 * mMinIconBackgroundCornerRadius) + - mMinIconBackgroundCornerRadius)) - mInnerMargin; + + // Menu dimensions + mMinimumMenuSize = + mIconViewMarginStart + mIconViewDrawableSize + mInnerMargin + iconArrowViewWidth; } @Override protected void onFinishInflate() { super.onFinishInflate(); mIconView = findViewById(R.id.icon_view); - mIconTextView = findViewById(R.id.icon_text); + mIconTextCollapsedView = findViewById(R.id.icon_text_collapsed); + mIconTextExpandedView = findViewById(R.id.icon_text_expanded); mIconArrowView = findViewById(R.id.icon_arrow); mIconViewBackground = findViewById(R.id.icon_view_background); + mIconViewBackgroundCornersStart = findViewById(R.id.icon_view_background_corners_start); + mIconViewBackgroundCornersEnd = findViewById(R.id.icon_view_background_corners_end); } protected IconView getIconView() { @@ -124,8 +165,11 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { @Override public void setText(CharSequence text) { - if (mIconTextView != null) { - mIconTextView.setText(text); + if (mIconTextCollapsedView != null) { + mIconTextCollapsedView.setText(text); + } + if (mIconTextExpandedView != null) { + mIconTextExpandedView.setText(text); } } @@ -148,83 +192,101 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { } } + /** + * Sets the maximum width of this Icon Menu. + */ + public void setMaxWidth(int maxWidth) { + // Only the app icon and caret are visible at its minimum width. + mMaxWidth = Math.max(maxWidth, mMinimumMenuSize); + } + @Override public void setIconOrientation(RecentsOrientedState orientationState, boolean isGridTask) { - PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler(); - boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; + boolean isRtl = isLayoutRtl(); DeviceProfile deviceProfile = ActivityContext.lookupContext(getContext()).getDeviceProfile(); - int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; - int taskIconSize = deviceProfile.overviewTaskIconSizePx; - int taskMargin = deviceProfile.overviewTaskMarginPx; - + // Layout Params for the Menu View + int thumbnailTopMargin = + deviceProfile.overviewTaskThumbnailTopMarginPx + mIconMenuMarginTop; LayoutParams iconMenuParams = (LayoutParams) getLayoutParams(); - orientationHandler.setTaskIconMenuParams(iconMenuParams, mIconMenuMarginStart, + orientationHandler.setIconAppChipMenuParams(this, iconMenuParams, mIconMenuMarginStart, thumbnailTopMargin); - iconMenuParams.width = mMinIconBackgroundWidth; - iconMenuParams.height = taskIconSize; - if (orientationHandler instanceof SeascapePagedViewHandler) { - // Use half menu height to place the pivot within the X/Y center of icon in the menu. - setPivotX(getHeight() / 2f); - setPivotY(getHeight() / 2f - mIconMenuMarginStart); - } else if (orientationHandler instanceof LandscapePagedViewHandler) { - setPivotX(getWidth()); - setPivotY(0); - } - // Pivot not updated for PortraitPagedViewHandler case, as it has 0 rotation. - - setTranslationY(0); - setRotation(orientationHandler.getDegreesRotated()); + iconMenuParams.width = Math.min(mMaxWidth, + mMinIconBackgroundWidth + (int) (2 * mMinIconBackgroundCornerRadius)); + iconMenuParams.height = mMinIconBackgroundHeight; + setLayoutParams(iconMenuParams); + // Layout Params for the Icon View LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams(); - orientationHandler.setTaskIconParams(iconParams, taskMargin, taskIconSize, - thumbnailTopMargin, isRtl); - iconParams.width = iconParams.height = taskIconSize; - iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL; + orientationHandler.setTaskIconParams(iconParams, mIconViewMarginStart, + mIconViewDrawableSize, thumbnailTopMargin, isRtl); + iconParams.width = iconParams.height = mIconViewDrawableSize; mIconView.setLayoutParams(iconParams); + mIconView.setDrawableSize(mIconViewDrawableSize, mIconViewDrawableSize); - int iconDrawableSize = enableOverviewIconMenu() - ? deviceProfile.overviewTaskIconAppChipMenuDrawableSizePx - : isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx - : deviceProfile.overviewTaskIconDrawableSizePx; - mIconView.setDrawableSize(iconDrawableSize, iconDrawableSize); - - LayoutParams iconTextParams = (LayoutParams) mIconTextView.getLayoutParams(); - orientationHandler.setTaskIconParams(iconTextParams, 0, taskIconSize, + // Layout Params for the collapsed Icon Text View + LayoutParams iconTextCollapsedParams = + (LayoutParams) mIconTextCollapsedView.getLayoutParams(); + orientationHandler.setTaskIconParams(iconTextCollapsedParams, 0, mIconViewDrawableSize, thumbnailTopMargin, isRtl); - iconTextParams.width = mIconTextMaxWidth; - iconTextParams.height = taskIconSize; - iconTextParams.setMarginStart(taskIconSize); - iconTextParams.topMargin = (getHeight() - mIconTextView.getHeight()) / 2; - iconTextParams.gravity = Gravity.CENTER_VERTICAL | Gravity.START; - mIconTextView.setLayoutParams(iconTextParams); - mIconTextView.setRevealClip(true, 0, taskIconSize / 2f, mIconTextMinWidth); + iconTextCollapsedParams.setMarginStart( + mIconViewDrawableSize + mIconViewMarginStart + mInnerMargin); + iconTextCollapsedParams.topMargin = (mMinIconBackgroundHeight - mIconViewDrawableSize) / 2; + iconTextCollapsedParams.gravity = Gravity.TOP | Gravity.START; + iconTextCollapsedParams.width = Math.min( + Math.max(mMaxWidth - mMinimumMenuSize - (2 * mInnerMargin), 0), mIconTextMinWidth); + mIconTextCollapsedView.setLayoutParams(iconTextCollapsedParams); + mIconTextCollapsedView.setAlpha(1f); + // Layout Params for the expanded Icon Text View + LayoutParams iconTextExpandedParams = + (LayoutParams) mIconTextExpandedView.getLayoutParams(); + orientationHandler.setTaskIconParams(iconTextExpandedParams, 0, mIconViewDrawableSize, + thumbnailTopMargin, isRtl); + iconTextExpandedParams.setMarginStart( + mIconViewDrawableSize + mIconViewMarginStart + mInnerMargin); + iconTextExpandedParams.topMargin = (mMinIconBackgroundHeight - mIconViewDrawableSize) / 2; + iconTextExpandedParams.gravity = Gravity.TOP | Gravity.START; + mIconTextExpandedView.setLayoutParams(iconTextExpandedParams); + mIconTextExpandedView.setAlpha(0f); + mIconTextExpandedView.setRevealClip(true, 0, mIconViewDrawableSize / 2f, mIconTextMinWidth); + + // Layout Params for the Icon Arrow View LayoutParams iconArrowParams = (LayoutParams) mIconArrowView.getLayoutParams(); iconArrowParams.gravity = Gravity.CENTER_VERTICAL | Gravity.END; - iconArrowParams.setMarginStart(taskIconSize + mIconTextMinWidth); iconArrowParams.setMarginEnd(mInnerMargin); mIconArrowView.setLayoutParams(iconArrowParams); - mIconArrowView.getDrawable().setBounds(0, 0, mIconArrowSize, mIconArrowSize); + // Layout Params for the Icon View Background and its corners + int cornerlessBackgroundWidth = (int) Math.min( + mMaxWidth - (2 * mMinIconBackgroundCornerRadius), mMinIconBackgroundWidth); + LayoutParams backgroundCornerEndParams = + (LayoutParams) mIconViewBackgroundCornersEnd.getLayoutParams(); + backgroundCornerEndParams.setMarginStart(cornerlessBackgroundWidth); + mIconViewBackgroundCornersEnd.setLayoutParams(backgroundCornerEndParams); LayoutParams backgroundParams = (LayoutParams) mIconViewBackground.getLayoutParams(); - backgroundParams.width = mMinIconBackgroundWidth; - backgroundParams.height = taskIconSize; - mIconViewBackground.setPivotX( - isRtl ? mMinIconBackgroundWidth - (taskIconSize / 2f - mInnerMargin) - : taskIconSize / 2f - mInnerMargin); - mIconViewBackground.setPivotY(taskIconSize / 2f); + backgroundParams.width = cornerlessBackgroundWidth; + backgroundParams.height = mMinIconBackgroundHeight; + backgroundParams.setMarginStart((int) mMinIconBackgroundCornerRadius); + mIconViewBackground.setLayoutParams(backgroundParams); + mIconViewBackground.setPivotX(isRtl ? cornerlessBackgroundWidth : 0); + mIconViewBackground.setPivotY(mMinIconBackgroundCornerRadius); - requestLayout(); + // This method is called twice sometimes (like when rotating split tasks). It is called + // once before onMeasure and onLayout, and again after onMeasure but before onLayout with + // a new width. This happens because we update widths on rotation and on measure of + // grouped task views. Calling requestLayout() does not guarantee a call to onMeasure if + // it has just measured, so we explicitly call it here. + measure(MeasureSpec.makeMeasureSpec(getLayoutParams().width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getLayoutParams().height, MeasureSpec.EXACTLY)); } @Override public void setIconColorTint(int color, float amount) { - if (mIconView != null) { - mIconView.setIconColorTint(color, amount); - } + // RecentsView's COLOR_TINT animates between 0 and 0.5f, we want to hide the app chip menu. + setAlpha(Utilities.mapToRange(amount, 0f, 0.5f, 1f, 0f, LINEAR)); } @Override @@ -239,37 +301,91 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { protected void revealAnim(boolean isRevealing) { if (isRevealing) { + boolean isRtl = isLayoutRtl(); + bringToFront(); ((AnimatedVectorDrawable) mIconArrowView.getDrawable()).start(); AnimatorSet anim = new AnimatorSet(); + float backgroundScaleY = mMaxIconBackgroundHeight / (float) mMinIconBackgroundHeight; + float maxCornerSize = Math.min(mMaxIconBackgroundHeight / 2f, + mMaxIconBackgroundCornerRadius); + float backgroundScaleX = (mMaxMenuWidth - (2 * maxCornerSize)) / Math.min( + mMaxWidth - (2 * mMinIconBackgroundCornerRadius), mMinIconBackgroundWidth); + float arrowTranslationX = mArrowMaxTranslationX + (mMinIconBackgroundWidth - Math.min( + mMaxWidth - (2 * mMinIconBackgroundCornerRadius), mMinIconBackgroundWidth)); + // Clip expanded text with reveal animation so it doesn't go beyond the edge of the menu + Animator expandedTextRevealAnim = ViewAnimationUtils.createCircularReveal( + mIconTextExpandedView, 0, mIconTextExpandedView.getHeight() / 2, 0, + mIconTextMaxWidth + maxCornerSize); + expandedTextRevealAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + // createCircularReveal removes clip on finish, restore it here to clip text. + mIconTextExpandedView.setRevealClip(true, 0, + mIconTextExpandedView.getHeight() / 2f, + mIconTextMaxWidth + maxCornerSize); + } + }); anim.playTogether( - ViewAnimationUtils.createCircularReveal(mIconTextView, 0, - mIconTextView.getHeight() / 2, mIconTextMinWidth, mIconTextMaxWidth), - ObjectAnimator.ofFloat(mIconViewBackground, SCALE_X, - mMaxIconBackgroundWidth / (float) mMinIconBackgroundWidth), - ObjectAnimator.ofFloat(mIconViewBackground, SCALE_Y, - mMaxIconBackgroundHeight / (float) mMinIconBackgroundHeight), + expandedTextRevealAnim, + ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_Y, + backgroundScaleY), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_X, + backgroundScaleY), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, SCALE_Y, + backgroundScaleY), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, SCALE_X, + backgroundScaleY), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, TRANSLATION_X, + isRtl ? -arrowTranslationX : arrowTranslationX), + ObjectAnimator.ofFloat(mIconViewBackground, SCALE_X, backgroundScaleX), + ObjectAnimator.ofFloat(mIconViewBackground, SCALE_Y, backgroundScaleY), + ObjectAnimator.ofFloat(mIconView, SCALE_X, + mIconViewDrawableMaxSize / (float) mIconViewDrawableSize), + ObjectAnimator.ofFloat(mIconView, SCALE_Y, + mIconViewDrawableMaxSize / (float) mIconViewDrawableSize), + ObjectAnimator.ofFloat(mIconTextCollapsedView, TRANSLATION_X, + isLayoutRtl() ? -mTextMaxTranslationX : mTextMaxTranslationX), + ObjectAnimator.ofFloat(mIconTextExpandedView, TRANSLATION_X, + isLayoutRtl() ? -mTextMaxTranslationX : mTextMaxTranslationX), + ObjectAnimator.ofFloat(mIconTextCollapsedView, ALPHA, 0), + ObjectAnimator.ofFloat(mIconTextExpandedView, ALPHA, 1), ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X, - isLayoutRtl() ? -mArrowMaxTranslationX : mArrowMaxTranslationX)); + isRtl ? -arrowTranslationX : arrowTranslationX)); anim.setDuration(MENU_BACKGROUND_REVEAL_DURATION); anim.setInterpolator(EMPHASIZED); anim.start(); } else { ((AnimatedVectorDrawable) mIconArrowView.getDrawable()).reverse(); - AnimatorSet anim = new AnimatorSet(); - Animator textRevealAnim = ViewAnimationUtils.createCircularReveal(mIconTextView, 0, - mIconTextView.getHeight() / 2, mIconTextMaxWidth, mIconTextMinWidth); - textRevealAnim.addListener(new AnimatorListenerAdapter() { + float maxCornerSize = Math.min(mMaxIconBackgroundHeight / 2f, + mMaxIconBackgroundCornerRadius); + // Clip expanded text with reveal animation so it doesn't go beyond the edge of the menu + Animator expandedTextClipAnim = ViewAnimationUtils.createCircularReveal( + mIconTextExpandedView, 0, mIconTextExpandedView.getHeight() / 2, + mIconTextMaxWidth + maxCornerSize, 0); + expandedTextClipAnim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // createCircularReveal removes clip on finish, restore it here to clip text. - mIconTextView.setRevealClip(true, 0, mIconTextView.getHeight() / 2f, - mIconTextMinWidth); + mIconTextExpandedView.setRevealClip(true, 0, + mIconTextExpandedView.getHeight() / 2f, 0); } }); + AnimatorSet anim = new AnimatorSet(); anim.playTogether( - textRevealAnim, + expandedTextClipAnim, + ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_X, 1), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersStart, SCALE_Y, 1), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, SCALE_X, 1), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, SCALE_Y, 1), + ObjectAnimator.ofFloat(mIconViewBackgroundCornersEnd, TRANSLATION_X, 0), ObjectAnimator.ofFloat(mIconViewBackground, SCALE_X, 1), ObjectAnimator.ofFloat(mIconViewBackground, SCALE_Y, 1), + ObjectAnimator.ofFloat(mIconView, SCALE_X, 1), + ObjectAnimator.ofFloat(mIconView, SCALE_Y, 1), + ObjectAnimator.ofFloat(mIconTextCollapsedView, TRANSLATION_X, 0), + ObjectAnimator.ofFloat(mIconTextExpandedView, TRANSLATION_X, 0), + ObjectAnimator.ofFloat(mIconTextCollapsedView, ALPHA, 1), + ObjectAnimator.ofFloat(mIconTextExpandedView, ALPHA, 0), ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X, 0)); anim.setDuration(MENU_BACKGROUND_HIDE_DURATION); anim.setInterpolator(EMPHASIZED); @@ -277,6 +393,24 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon { } } + protected void reset() { + mIconViewBackgroundCornersStart.setScaleX(1); + mIconViewBackgroundCornersStart.setScaleY(1); + mIconViewBackgroundCornersEnd.setScaleX(1); + mIconViewBackgroundCornersEnd.setScaleY(1); + mIconViewBackgroundCornersEnd.setTranslationX(0); + mIconViewBackground.setScaleX(1); + mIconViewBackground.setScaleY(1); + mIconView.setScaleX(1); + mIconView.setScaleY(1); + mIconTextCollapsedView.setTranslationX(0); + mIconTextExpandedView.setTranslationX(0); + mIconTextCollapsedView.setAlpha(1); + mIconTextExpandedView.setAlpha(0); + mIconArrowView.setTranslationX(0); + ((AnimatedVectorDrawable) mIconArrowView.getDrawable()).reset(); + } + @Override public View asView() { return this; diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 79729999f3..f55dce9ea2 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -34,6 +34,7 @@ import static com.android.app.animation.Interpolators.clampToProgress; import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU; import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; +import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; @@ -42,7 +43,6 @@ import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.Utilities.squaredHypot; import static com.android.launcher3.Utilities.squaredTouchSlop; -import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP; @@ -2032,12 +2032,12 @@ public abstract class RecentsView + android:centerColor="?androidprv:attr/materialColorSurfaceBright" + android:endColor="?androidprv:attr/materialColorSurfaceBright" /> \ No newline at end of file diff --git a/res/drawable/icon_menu_background.xml b/res/drawable/icon_menu_background.xml index ec5f0117df..8a95c3ecb4 100644 --- a/res/drawable/icon_menu_background.xml +++ b/res/drawable/icon_menu_background.xml @@ -17,6 +17,5 @@ - - + \ No newline at end of file diff --git a/res/drawable/icon_menu_background_corners.xml b/res/drawable/icon_menu_background_corners.xml new file mode 100644 index 0000000000..16e3fe26f3 --- /dev/null +++ b/res/drawable/icon_menu_background_corners.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index c0a1e0a605..3b404d6cb3 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -402,9 +402,12 @@ 0dp 0dp 0dp + 0dp + 0dp + 0dp 0dp 0dp - 0dp + 0dp 0dp 0dp 0dp diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index c80f243120..51c047c67c 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -22,12 +22,13 @@ import static android.view.Gravity.END; import static android.view.Gravity.LEFT; import static android.view.Gravity.START; import static android.view.Gravity.TOP; +import static android.view.View.LAYOUT_DIRECTION_RTL; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static com.android.launcher3.Flags.enableOverviewIconMenu; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; -import static com.android.launcher3.Flags.enableOverviewIconMenu; 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; @@ -41,6 +42,7 @@ import android.graphics.RectF; import android.graphics.drawable.ShapeDrawable; import android.util.FloatProperty; import android.util.Pair; +import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; @@ -270,7 +272,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { public float getTaskMenuX(float x, View thumbnailView, DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) { if (enableOverviewIconMenu()) { - return x - (taskInsetMargin / 2f); + return x + (taskInsetMargin / 2f); } return thumbnailView.getMeasuredWidth() + x - taskInsetMargin; } @@ -279,7 +281,10 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { public float getTaskMenuY(float y, View thumbnailView, int stagePosition, View taskMenuView, float taskInsetMargin, View taskViewIcon) { if (enableOverviewIconMenu()) { - return y - taskMenuView.getMeasuredHeight() - taskInsetMargin; + return y - (thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL + ? taskMenuView.getMeasuredHeight() * 2 - (taskInsetMargin / 2f) + : taskMenuView.getMeasuredHeight()); + } BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams(); int taskMenuWidth = lp.width; @@ -294,6 +299,10 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, @StagePosition int stagePosition) { + if (enableOverviewIconMenu()) { + return thumbnailView.getResources().getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_max_width); + } if (stagePosition == SplitConfigurationOptions.STAGE_POSITION_UNDEFINED) { return thumbnailView.getMeasuredWidth(); } else { @@ -323,7 +332,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { public Pair getDwbLayoutTranslations(int taskViewWidth, int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile, View[] thumbnailViews, int desiredTaskId, View banner) { - boolean isRtl = banner.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + boolean isRtl = banner.getLayoutDirection() == LAYOUT_DIRECTION_RTL; float translationX = 0; float translationY = 0; FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams(); @@ -504,8 +513,19 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot, - int parentWidth, int parentHeight, SplitBounds splitBoundsConfig, - DeviceProfile dp, boolean isRtl) { + int parentWidth, int parentHeight, SplitBounds splitBoundsConfig, DeviceProfile dp, + boolean isRtl) { + FrameLayout.LayoutParams primaryParams = + (FrameLayout.LayoutParams) primarySnapshot.getLayoutParams(); + FrameLayout.LayoutParams secondaryParams = + (FrameLayout.LayoutParams) secondarySnapshot.getLayoutParams(); + + // Swap the margins that are set in TaskView#setRecentsOrientedState() + secondaryParams.topMargin = dp.overviewTaskThumbnailTopMarginPx; + primaryParams.topMargin = 0; + + // Measure and layout the thumbnails bottom up, since the primary is on the visual left + // (portrait bottom) and secondary is on the right (portrait top) int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx; int totalThumbnailHeight = parentHeight - spaceAboveSnapshot; int dividerBar = Math.round(totalThumbnailHeight * (splitBoundsConfig.appsStackedVertically @@ -519,11 +539,12 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { float taskPercent = splitBoundsConfig.appsStackedVertically ? splitBoundsConfig.topTaskPercent : splitBoundsConfig.leftTaskPercent; primarySnapshotWidth = parentWidth; - primarySnapshotHeight = (int) (totalThumbnailHeight * taskPercent); + primarySnapshotHeight = (int) (totalThumbnailHeight * (taskPercent)); secondarySnapshotWidth = parentWidth; secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar; - secondarySnapshot.setTranslationY(primarySnapshotHeight + spaceAboveSnapshot + dividerBar); + secondarySnapshot.setTranslationY(0); + primarySnapshot.setTranslationY(secondarySnapshotHeight + spaceAboveSnapshot + dividerBar); primarySnapshot.measure( View.MeasureSpec.makeMeasureSpec(primarySnapshotWidth, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(primarySnapshotHeight, View.MeasureSpec.EXACTLY)); @@ -536,6 +557,11 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) { + if (enableOverviewIconMenu()) { + iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL; + iconParams.topMargin = 0; + return; + } iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL; iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2; iconParams.leftMargin = 0; @@ -544,13 +570,21 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { } @Override - public void setTaskIconMenuParams(FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, - int thumbnailTopMargin) { - iconMenuParams.gravity = END | TOP; - iconMenuParams.setMarginStart(0); - iconMenuParams.topMargin = iconMenuParams.width + iconMenuMargin; - iconMenuParams.bottomMargin = 0; + public void setIconAppChipMenuParams(View iconAppChipMenuView, + FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) { + boolean isRtl = iconAppChipMenuView.getLayoutDirection() == LAYOUT_DIRECTION_RTL; + iconMenuParams.gravity = (isRtl ? START : END) | (isRtl ? BOTTOM : TOP); + iconMenuParams.setMarginStart(isRtl ? iconMenuMargin : 0); + iconMenuParams.topMargin = iconMenuMargin; + iconMenuParams.bottomMargin = isRtl ? iconMenuMargin : 0; iconMenuParams.setMarginEnd(iconMenuMargin); + + iconAppChipMenuView.setPivotX(isRtl ? iconMenuParams.width - (iconMenuParams.height / 2f) + : iconMenuParams.width / 2f); + iconAppChipMenuView.setPivotY( + isRtl ? (iconMenuParams.height / 2f) : iconMenuParams.width / 2f); + iconAppChipMenuView.setTranslationY(0); + iconAppChipMenuView.setRotation(getDegreesRotated()); } @Override @@ -578,16 +612,23 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct); int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct); - primaryIconParams.gravity = enableOverviewIconMenu() ? TOP | (isRtl ? START : END) - : BOTTOM | (isRtl ? START : END); - secondaryIconParams.gravity = enableOverviewIconMenu() ? TOP | (isRtl ? START : END) - : BOTTOM | (isRtl ? START : END); + if (enableOverviewIconMenu()) { + primaryIconParams.gravity = isRtl ? BOTTOM | START : TOP | END; + secondaryIconParams.gravity = isRtl ? BOTTOM | START : TOP | END; + } else { + primaryIconParams.gravity = BOTTOM | (isRtl ? START : END); + secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END); + } primaryIconView.setTranslationX(0); secondaryIconView.setTranslationX(0); if (enableOverviewIconMenu()) { - int dividerThickness = Math.min(splitConfig.visualDividerBounds.width(), - splitConfig.visualDividerBounds.height()); - secondaryIconView.setTranslationY(primarySnapshotHeight + dividerThickness); + if (primaryIconView.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + secondaryIconView.setTranslationY(-primarySnapshotHeight); + primaryIconView.setTranslationY(0); + } else { + int secondarySnapshotHeight = groupedTaskViewHeight - primarySnapshotHeight; + primaryIconView.setTranslationY(secondarySnapshotHeight); + } } else if (splitConfig.initiatedFromSeascape) { // if the split was initiated from seascape, // the task on the right (secondary) is slightly larger diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 0069d9bcaf..74d88ba922 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -173,8 +173,8 @@ public interface PagedOrientationHandler { // Overview TaskMenuView methods void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl); - void setTaskIconMenuParams(FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, - int thumbnailTopMargin); + void setIconAppChipMenuParams(View iconAppChipMenuView, FrameLayout.LayoutParams iconMenuParams, + int iconMenuMargin, int thumbnailTopMargin); void setSplitIconParams(View primaryIconView, View secondaryIconView, int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight, int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl, diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 62ef2295c0..158747cc7c 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -25,9 +25,9 @@ import static android.view.View.LAYOUT_DIRECTION_RTL; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static com.android.launcher3.Flags.enableOverviewIconMenu; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; -import static com.android.launcher3.Flags.enableOverviewIconMenu; import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; @@ -41,6 +41,7 @@ import android.graphics.RectF; import android.graphics.drawable.ShapeDrawable; import android.util.FloatProperty; import android.util.Pair; +import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; @@ -268,8 +269,10 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { public float getTaskMenuX(float x, View thumbnailView, DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) { if (enableOverviewIconMenu()) { - return x + (thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL - ? -(taskViewIcon.getWidth() / 2f) : 0); + if (thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + return x + taskInsetMargin - taskViewIcon.getHeight() - (taskInsetMargin / 2f); + } + return x + taskInsetMargin; } else if (deviceProfile.isLandscape) { return x + taskInsetMargin + (thumbnailView.getMeasuredWidth() - thumbnailView.getMeasuredHeight()) / 2f; @@ -291,14 +294,14 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { public int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile, @StagePosition int stagePosition) { if (enableOverviewIconMenu()) { - int padding = thumbnailView.getResources().getDimensionPixelSize( - R.dimen.task_menu_vertical_padding); return thumbnailView.getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_icon_menu_max_width) + (2 * padding); + R.dimen.task_thumbnail_icon_menu_max_width); } - return deviceProfile.isLandscape && !deviceProfile.isTablet + int padding = thumbnailView.getResources() + .getDimensionPixelSize(R.dimen.task_menu_edge_padding); + return (deviceProfile.isLandscape && !deviceProfile.isTablet ? thumbnailView.getMeasuredHeight() - : thumbnailView.getMeasuredWidth(); + : thumbnailView.getMeasuredWidth()) - (2 * padding); } @Override @@ -696,6 +699,12 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { @Override public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) { + if (enableOverviewIconMenu()) { + iconParams.setMarginStart(taskIconMargin); + iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL; + iconParams.topMargin = 0; + return; + } iconParams.gravity = TOP | CENTER_HORIZONTAL; // Reset margins, since they may have been set on rotation iconParams.leftMargin = iconParams.rightMargin = 0; @@ -703,13 +712,18 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } @Override - public void setTaskIconMenuParams(FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, - int thumbnailTopMargin) { + public void setIconAppChipMenuParams(View iconAppChipMenuView, + FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) { iconMenuParams.gravity = TOP | START; iconMenuParams.setMarginStart(iconMenuMargin); - iconMenuParams.topMargin = iconMenuMargin; + iconMenuParams.topMargin = thumbnailTopMargin; iconMenuParams.bottomMargin = 0; iconMenuParams.setMarginEnd(0); + + iconAppChipMenuView.setPivotX(0); + iconAppChipMenuView.setPivotY(0); + iconAppChipMenuView.setTranslationY(0); + iconAppChipMenuView.setRotation(getDegreesRotated()); } @Override @@ -729,20 +743,13 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { secondaryIconParams.topMargin = primaryIconParams.topMargin; secondaryIconParams.setMarginStart(primaryIconParams.getMarginStart()); if (deviceProfile.isLandscape) { - int fullscreenInsetThickness = deviceProfile.isSeascape() - ? deviceProfile.getInsets().right - : deviceProfile.getInsets().left; - int fullscreenMidpointFromBottom = ((deviceProfile.widthPx - - fullscreenInsetThickness) / 2); - float midpointFromEndPct = (float) fullscreenMidpointFromBottom - / deviceProfile.widthPx; - int bottomToMidpointOffset = (int) (groupedTaskViewWidth * midpointFromEndPct); if (isRtl) { - primaryIconView.setTranslationX(-bottomToMidpointOffset); + primaryIconView.setTranslationX(-primarySnapshotWidth); } else { - secondaryIconView.setTranslationX(bottomToMidpointOffset); + secondaryIconView.setTranslationX(primarySnapshotWidth); } } else { + primaryIconView.setTranslationX(0); secondaryIconView.setTranslationX(0); int dividerThickness = Math.min(splitConfig.visualDividerBounds.width(), splitConfig.visualDividerBounds.height()); diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java index 44095728e5..06526a876e 100644 --- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java @@ -21,6 +21,8 @@ import static android.view.Gravity.CENTER_VERTICAL; import static android.view.Gravity.END; import static android.view.Gravity.RIGHT; import static android.view.Gravity.START; +import static android.view.Gravity.TOP; +import static android.view.View.LAYOUT_DIRECTION_RTL; import static com.android.launcher3.Flags.enableOverviewIconMenu; import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL; @@ -32,6 +34,7 @@ import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.util.Pair; +import android.view.Gravity; import android.view.Surface; import android.view.View; import android.widget.FrameLayout; @@ -89,7 +92,7 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { public float getTaskMenuX(float x, View thumbnailView, DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) { if (enableOverviewIconMenu()) { - return x + taskViewIcon.getHeight() + taskInsetMargin * 2; + return x + (taskViewIcon.getHeight() * 2); } return x + taskInsetMargin; } @@ -98,7 +101,9 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { public float getTaskMenuY(float y, View thumbnailView, int stagePosition, View taskMenuView, float taskInsetMargin, View taskViewIcon) { if (enableOverviewIconMenu()) { - return y + taskViewIcon.getWidth() - taskViewIcon.getHeight(); + return y + taskViewIcon.getWidth() + ( + thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL ? taskInsetMargin + / 2f : -taskViewIcon.getHeight()); } BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams(); int taskMenuWidth = lp.width; @@ -134,7 +139,7 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { public Pair getDwbLayoutTranslations(int taskViewWidth, int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile, View[] thumbnailViews, int desiredTaskId, View banner) { - boolean isRtl = banner.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + boolean isRtl = banner.getLayoutDirection() == LAYOUT_DIRECTION_RTL; float translationX = 0; float translationY = 0; FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams(); @@ -214,22 +219,37 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { @Override public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) { - iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL; - iconParams.leftMargin = - enableOverviewIconMenu() ? 0 : -taskIconHeight - taskIconMargin / 2; iconParams.rightMargin = 0; - iconParams.topMargin = enableOverviewIconMenu() ? 0 : thumbnailTopMargin / 2; iconParams.bottomMargin = 0; + if (enableOverviewIconMenu()) { + iconParams.setMarginStart(taskIconMargin); + iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL; + iconParams.leftMargin = 0; + iconParams.topMargin = 0; + } else { + iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL; + iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2; + iconParams.topMargin = thumbnailTopMargin / 2; + } } @Override - public void setTaskIconMenuParams(FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, - int thumbnailTopMargin) { - iconMenuParams.gravity = BOTTOM | START; + public void setIconAppChipMenuParams(View iconAppChipMenuView, + FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) { + boolean isRtl = iconAppChipMenuView.getLayoutDirection() == LAYOUT_DIRECTION_RTL; + iconMenuParams.gravity = (isRtl ? TOP : BOTTOM) | (isRtl ? END : START); iconMenuParams.setMarginStart(0); - iconMenuParams.topMargin = 0; + iconMenuParams.topMargin = isRtl ? iconMenuMargin : 0; iconMenuParams.bottomMargin = 0; - iconMenuParams.setMarginEnd(0); + iconMenuParams.setMarginEnd(isRtl ? thumbnailTopMargin : 0); + + // Use half menu height to place the pivot within the X/Y center of icon in the menu. + float iconCenter = iconAppChipMenuView.getHeight() / 2f; + iconAppChipMenuView.setPivotX(isRtl ? iconMenuParams.width / 2f : iconCenter); + iconAppChipMenuView.setPivotY( + isRtl ? iconMenuParams.width / 2f : iconCenter - iconMenuMargin); + iconAppChipMenuView.setTranslationY(0); + iconAppChipMenuView.setRotation(getDegreesRotated()); } @Override @@ -259,14 +279,19 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler { int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct); int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct); - primaryIconParams.gravity = BOTTOM | (isRtl ? END : START); - secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START); + int gravity = (isRtl ? TOP : BOTTOM) | (isRtl ? END : START); + primaryIconParams.gravity = gravity; + secondaryIconParams.gravity = gravity; primaryIconView.setTranslationX(0); secondaryIconView.setTranslationX(0); if (enableOverviewIconMenu()) { - int dividerThickness = Math.min(splitConfig.visualDividerBounds.width(), - splitConfig.visualDividerBounds.height()); - secondaryIconView.setTranslationY(-primarySnapshotHeight - dividerThickness); + if (primaryIconView.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + primaryIconView.setTranslationY(groupedTaskViewHeight - primarySnapshotHeight); + secondaryIconView.setTranslationY(0); + } else { + secondaryIconView.setTranslationY(-primarySnapshotHeight); + primaryIconView.setTranslationY(0); + } } else if (splitConfig.initiatedFromSeascape) { // if the split was initiated from seascape, // the task on the right (secondary) is slightly larger