App chip refactor

- Adds background outline replacing 2 circles + rect approach. This
enables easier shadow drawing code.
- Simplify structure of AppChipView.
- Adds an anchor View to simplify laying out of menu around app chip

Bug: 313644427
Bug: 317007147
Fix: 322760765
Flag: ACONFIG com.android.launcher3.enable_grid_only_overview TEAMFOOD
Flag: ACONFIG com.android.launcher3.enable_overview_icon_menu TEAMFOOD
Test: OverviewImageTest
Change-Id: I56c2644779863c083ae475a740a84321b1d0c396
This commit is contained in:
Uwais Ashraf
2024-02-05 13:18:58 +00:00
parent e35d5d8cb0
commit 99fdf7a75e
27 changed files with 276 additions and 432 deletions
@@ -274,21 +274,12 @@ public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler
@Override
public float getTaskMenuX(float x, View thumbnailView,
DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) {
if (enableOverviewIconMenu()) {
return x + (taskInsetMargin / 2f);
}
return thumbnailView.getMeasuredWidth() + x - taskInsetMargin;
}
@Override
public float getTaskMenuY(float y, View thumbnailView, int stagePosition,
View taskMenuView, float taskInsetMargin, View taskViewIcon) {
if (enableOverviewIconMenu()) {
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;
if (stagePosition == STAGE_POSITION_UNDEFINED) {
@@ -304,7 +295,7 @@ public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler
@StagePosition int stagePosition) {
if (enableOverviewIconMenu()) {
return thumbnailView.getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_max_width);
R.dimen.task_thumbnail_icon_menu_expanded_width);
}
if (stagePosition == SplitConfigurationOptions.STAGE_POSITION_UNDEFINED) {
return thumbnailView.getMeasuredWidth();
@@ -582,11 +573,6 @@ public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler
@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;
@@ -594,6 +580,14 @@ public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler
iconParams.bottomMargin = 0;
}
@Override
public void setIconAppChipChildrenParams(FrameLayout.LayoutParams iconParams,
int chipChildMarginStart) {
iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
iconParams.setMarginStart(chipChildMarginStart);
iconParams.topMargin = 0;
}
@Override
public void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) {
@@ -21,7 +21,6 @@ import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.view.Gravity.END;
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;
@@ -182,12 +181,7 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
@Override
public float getTaskMenuX(float x, View thumbnailView,
DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) {
if (enableOverviewIconMenu()) {
if (thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
return x + taskInsetMargin - taskViewIcon.getHeight() - (taskInsetMargin / 2f);
}
return x + taskInsetMargin;
} else if (deviceProfile.isLandscape) {
if (deviceProfile.isLandscape) {
return x + taskInsetMargin
+ (thumbnailView.getMeasuredWidth() - thumbnailView.getMeasuredHeight()) / 2f;
} else {
@@ -198,9 +192,6 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
@Override
public float getTaskMenuY(float y, View thumbnailView, int stagePosition,
View taskMenuView, float taskInsetMargin, View taskViewIcon) {
if (enableOverviewIconMenu()) {
return y;
}
return y + taskInsetMargin;
}
@@ -209,7 +200,7 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
@StagePosition int stagePosition) {
if (enableOverviewIconMenu()) {
return thumbnailView.getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_max_width);
R.dimen.task_thumbnail_icon_menu_expanded_width);
}
int padding = thumbnailView.getResources()
.getDimensionPixelSize(R.dimen.task_menu_edge_padding);
@@ -623,18 +614,20 @@ public class PortraitPagedViewHandler extends DefaultPagedViewHandler implements
@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;
iconParams.topMargin = iconParams.bottomMargin = 0;
}
@Override
public void setIconAppChipChildrenParams(FrameLayout.LayoutParams iconParams,
int chipChildMarginStart) {
iconParams.setMarginStart(chipChildMarginStart);
iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
iconParams.topMargin = 0;
}
@Override
public void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) {
@@ -146,9 +146,16 @@ public interface RecentsPagedOrientationHandler extends PagedOrientationHandler
int parentWidth, int parentHeight);
// Overview TaskMenuView methods
/** Sets layout params on a task's app icon. Only use this when app chip is disabled. */
void setTaskIconParams(FrameLayout.LayoutParams iconParams,
int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
/**
* Sets layout params on the children of an app chip. Only use this when app chip is enabled.
*/
void setIconAppChipChildrenParams(
FrameLayout.LayoutParams iconParams, int chipChildMarginStart);
void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
FrameLayout.LayoutParams iconMenuParams,
int iconMenuMargin, int thumbnailTopMargin);
@@ -94,9 +94,6 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
@Override
public float getTaskMenuX(float x, View thumbnailView,
DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) {
if (enableOverviewIconMenu()) {
return x + (taskViewIcon.getHeight() * 2);
}
return x + taskInsetMargin;
}
@@ -104,9 +101,7 @@ 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() + (
thumbnailView.getLayoutDirection() == LAYOUT_DIRECTION_RTL ? taskInsetMargin
/ 2f : -taskViewIcon.getHeight());
return y;
}
BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams();
int taskMenuWidth = lp.width;
@@ -222,18 +217,16 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
@Override
public void setTaskIconParams(FrameLayout.LayoutParams iconParams,
int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
iconParams.rightMargin = 0;
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;
}
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
iconParams.setMargins(-taskIconHeight - taskIconMargin / 2, thumbnailTopMargin / 2, 0, 0);
}
@Override
public void setIconAppChipChildrenParams(FrameLayout.LayoutParams iconParams,
int chipChildMarginStart) {
iconParams.setMargins(0, 0, 0, 0);
iconParams.setMarginStart(chipChildMarginStart);
iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
}
@Override
@@ -398,8 +398,11 @@ public class GroupedTaskView extends TaskView {
layoutParams.width,
layoutParams.height
);
int iconMargins = getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_start_margin) * 2;
int iconViewMarginStart = getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin);
int iconViewBackgroundMarginStart = getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_background_margin_top_start);
int iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2;
((IconAppChipView) mIconView).setMaxWidth(groupedTaskViewSizes.first.x - iconMargins);
((IconAppChipView) mIconView2).setMaxWidth(groupedTaskViewSizes.second.x - iconMargins);
}
@@ -17,30 +17,32 @@ package com.android.quickstep.views;
import static com.android.app.animation.Interpolators.EMPHASIZED;
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
import com.android.quickstep.util.RecentsOrientedState;
@@ -59,34 +61,28 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
private final MultiValueAlpha mMultiValueAlpha;
private View mMenuAnchorView;
private IconView mIconView;
// 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 final int mMinimumMenuSize;
private final int mMaxMenuWidth;
private final int mIconMenuMarginTop;
private final int mIconMenuMarginStart;
private final Rect mBackgroundRelativeLtrLocation = new Rect();
final RectEvaluator mBackgroundAnimationRectEvaluator =
new RectEvaluator(mBackgroundRelativeLtrLocation);
private final int mCollapsedMenuDefaultWidth;
private final int mExpandedMenuDefaultWidth;
private final int mCollapsedMenuDefaultHeight;
private final int mExpandedMenuDefaultHeight;
private final int mIconMenuMarginTopStart;
private final int mMenuToChipGap;
private final int mBackgroundMarginTopStart;
private final int mAppNameHorizontalMargin;
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 final int mAppIconSize;
private final int mArrowSize;
private final int mIconViewDrawableExpandedSize;
private final int mArrowMarginEnd;
private AnimatorSet mAnimator;
private int mMaxWidth = Integer.MAX_VALUE;
@@ -111,51 +107,35 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
mMultiValueAlpha.setUpdateVisibility(/* updateVisibility= */ true);
// 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);
mCollapsedMenuDefaultWidth =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_collapsed_width);
mExpandedMenuDefaultWidth =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_expanded_width);
mCollapsedMenuDefaultHeight =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_collapsed_height);
mExpandedMenuDefaultHeight =
res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_expanded_height);
mIconMenuMarginTopStart = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_expanded_top_start_margin);
mMenuToChipGap = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_expanded_gap);
// 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 = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_min_height);
mMaxIconBackgroundCornerRadius = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_corner_radius);
mBackgroundMarginTopStart = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_background_margin_top_start);
// 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);
// IconView dimensions
// Contents dimensions
mAppNameHorizontalMargin = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_app_name_margin_horizontal_collapsed);
mArrowMarginEnd = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_arrow_margin);
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(
mAppIconSize = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_app_icon_collapsed_size);
mArrowSize = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_arrow_size);
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;
mIconViewDrawableExpandedSize = res.getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_app_icon_expanded_size);
}
@Override
@@ -165,9 +145,7 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
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);
mMenuAnchorView = findViewById(R.id.icon_view_menu_anchor);
}
protected IconView getIconView() {
@@ -204,88 +182,85 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
}
/**
* Sets the maximum width of this Icon Menu.
* Sets the maximum width of this Icon Menu. This is usually used when space is limited for
* split screen.
*/
public void setMaxWidth(int maxWidth) {
// Only the app icon and caret are visible at its minimum width.
mMaxWidth = Math.max(maxWidth, mMinimumMenuSize);
// Width showing only the app icon and arrow. Max width should not be set to less than this.
int minimumMaxWidth = mIconViewMarginStart + mAppIconSize + mArrowSize + mArrowMarginEnd;
mMaxWidth = Math.max(maxWidth, minimumMaxWidth);
}
@Override
public void setIconOrientation(RecentsOrientedState orientationState, boolean isGridTask) {
RecentsPagedOrientationHandler orientationHandler =
orientationState.getOrientationHandler();
boolean isRtl = isLayoutRtl();
DeviceProfile deviceProfile =
ActivityContext.lookupContext(getContext()).getDeviceProfile();
// Layout params for anchor view
LayoutParams anchorLayoutParams = (LayoutParams) mMenuAnchorView.getLayoutParams();
anchorLayoutParams.topMargin = mExpandedMenuDefaultHeight + mMenuToChipGap;
mMenuAnchorView.setLayoutParams(anchorLayoutParams);
// Layout Params for the Menu View
int thumbnailTopMargin =
deviceProfile.overviewTaskThumbnailTopMarginPx + mIconMenuMarginTop;
// Layout Params for the Menu View (this)
LayoutParams iconMenuParams = (LayoutParams) getLayoutParams();
orientationHandler.setIconAppChipMenuParams(this, iconMenuParams, mIconMenuMarginStart,
thumbnailTopMargin);
iconMenuParams.width = Math.min(mMaxWidth,
mMinIconBackgroundWidth + (int) (2 * mMinIconBackgroundCornerRadius));
iconMenuParams.height = mMinIconBackgroundHeight;
iconMenuParams.width = mExpandedMenuDefaultWidth;
iconMenuParams.height = mExpandedMenuDefaultHeight;
orientationHandler.setIconAppChipMenuParams(this, iconMenuParams, mIconMenuMarginTopStart,
mIconMenuMarginTopStart);
setLayoutParams(iconMenuParams);
// Layout params for the background
Rect collapsedBackgroundBounds = getCollapsedBackgroundLtrBounds();
mBackgroundRelativeLtrLocation.set(collapsedBackgroundBounds);
setOutlineProvider(new ViewOutlineProvider() {
final Rect mRtlAppliedOutlineBounds = new Rect();
@Override
public void getOutline(View view, Outline outline) {
mRtlAppliedOutlineBounds.set(mBackgroundRelativeLtrLocation);
if (isLayoutRtl()) {
int width = getWidth();
mRtlAppliedOutlineBounds.left = width - mBackgroundRelativeLtrLocation.right;
mRtlAppliedOutlineBounds.right = width - mBackgroundRelativeLtrLocation.left;
}
outline.setRoundRect(
mRtlAppliedOutlineBounds, mRtlAppliedOutlineBounds.height() / 2f);
}
});
// Layout Params for the Icon View
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
orientationHandler.setTaskIconParams(iconParams, mIconViewMarginStart,
mIconViewDrawableSize, thumbnailTopMargin, isRtl);
iconParams.width = iconParams.height = mIconViewDrawableSize;
int iconMarginStartRelativeToParent = mIconViewMarginStart + mBackgroundMarginTopStart;
orientationHandler.setIconAppChipChildrenParams(
iconParams, iconMarginStartRelativeToParent);
mIconView.setLayoutParams(iconParams);
mIconView.setDrawableSize(mIconViewDrawableSize, mIconViewDrawableSize);
mIconView.setDrawableSize(mAppIconSize, mAppIconSize);
// Layout Params for the collapsed Icon Text View
int textMarginStart =
iconMarginStartRelativeToParent + mAppIconSize + mAppNameHorizontalMargin;
LayoutParams iconTextCollapsedParams =
(LayoutParams) mIconTextCollapsedView.getLayoutParams();
orientationHandler.setTaskIconParams(iconTextCollapsedParams, 0, mIconViewDrawableSize,
thumbnailTopMargin, isRtl);
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);
orientationHandler.setIconAppChipChildrenParams(iconTextCollapsedParams, textMarginStart);
int collapsedTextWidth = collapsedBackgroundBounds.width() - mIconViewMarginStart
- mAppIconSize - mArrowSize - mAppNameHorizontalMargin - mArrowMarginEnd;
iconTextCollapsedParams.width = collapsedTextWidth;
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;
orientationHandler.setIconAppChipChildrenParams(iconTextExpandedParams, textMarginStart);
mIconTextExpandedView.setLayoutParams(iconTextExpandedParams);
mIconTextExpandedView.setAlpha(0f);
mIconTextExpandedView.setRevealClip(true, 0, mIconViewDrawableSize / 2f, mIconTextMinWidth);
mIconTextExpandedView.setRevealClip(true, 0, mAppIconSize / 2f, collapsedTextWidth);
// Layout Params for the Icon Arrow View
LayoutParams iconArrowParams = (LayoutParams) mIconArrowView.getLayoutParams();
iconArrowParams.gravity = Gravity.CENTER_VERTICAL | Gravity.END;
iconArrowParams.setMarginEnd(mInnerMargin);
int arrowMarginStart = collapsedBackgroundBounds.right - mArrowMarginEnd - mArrowSize;
orientationHandler.setIconAppChipChildrenParams(iconArrowParams, arrowMarginStart);
mIconArrowView.setLayoutParams(iconArrowParams);
// 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 = cornerlessBackgroundWidth;
backgroundParams.height = mMinIconBackgroundHeight;
backgroundParams.setMarginStart((int) mMinIconBackgroundCornerRadius);
mIconViewBackground.setLayoutParams(backgroundParams);
mIconViewBackground.setPivotX(isRtl ? cornerlessBackgroundWidth : 0);
mIconViewBackground.setPivotY(mMinIconBackgroundCornerRadius);
// 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
@@ -324,108 +299,96 @@ public class IconAppChipView extends FrameLayout implements TaskViewIcon {
protected void revealAnim(boolean isRevealing) {
cancelInProgressAnimations();
final Rect collapsedBackgroundBounds = getCollapsedBackgroundLtrBounds();
final Rect expandedBackgroundBounds = getExpandedBackgroundLtrBounds();
final Rect initialBackground = new Rect(mBackgroundRelativeLtrLocation);
mAnimator = new AnimatorSet();
if (isRevealing) {
boolean isRtl = isLayoutRtl();
bringToFront();
((AnimatedVectorDrawable) mIconArrowView.getDrawable()).start();
mAnimator = 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);
}
});
mIconTextExpandedView, 0, mIconTextExpandedView.getHeight() / 2,
mIconTextCollapsedView.getWidth(), mIconTextExpandedView.getWidth());
// Animate background clipping
ValueAnimator backgroundAnimator = ValueAnimator.ofObject(
mBackgroundAnimationRectEvaluator,
initialBackground,
expandedBackgroundBounds);
backgroundAnimator.addUpdateListener(valueAnimator -> invalidateOutline());
float iconViewScaling = mIconViewDrawableExpandedSize / (float) mAppIconSize;
float arrowTranslationX =
expandedBackgroundBounds.right - collapsedBackgroundBounds.right;
float iconCenterToTextCollapsed = mAppIconSize / 2f + mAppNameHorizontalMargin;
float iconCenterToTextExpanded =
mIconViewDrawableExpandedSize / 2f + mAppNameHorizontalMargin;
float textTranslationX = iconCenterToTextExpanded - iconCenterToTextCollapsed;
float textTranslationXWithRtl = isRtl ? -textTranslationX : textTranslationX;
float arrowTranslationWithRtl = isRtl ? -arrowTranslationX : arrowTranslationX;
mAnimator.playTogether(
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),
backgroundAnimator,
ObjectAnimator.ofFloat(mIconView, SCALE_X, iconViewScaling),
ObjectAnimator.ofFloat(mIconView, SCALE_Y, iconViewScaling),
ObjectAnimator.ofFloat(mIconTextCollapsedView, TRANSLATION_X,
isLayoutRtl() ? -mTextMaxTranslationX : mTextMaxTranslationX),
textTranslationXWithRtl),
ObjectAnimator.ofFloat(mIconTextExpandedView, TRANSLATION_X,
isLayoutRtl() ? -mTextMaxTranslationX : mTextMaxTranslationX),
textTranslationXWithRtl),
ObjectAnimator.ofFloat(mIconTextCollapsedView, ALPHA, 0),
ObjectAnimator.ofFloat(mIconTextExpandedView, ALPHA, 1),
ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X,
isRtl ? -arrowTranslationX : arrowTranslationX));
ObjectAnimator.ofFloat(mIconArrowView, TRANSLATION_X, arrowTranslationWithRtl));
mAnimator.setDuration(MENU_BACKGROUND_REVEAL_DURATION);
mAnimator.setInterpolator(EMPHASIZED);
mAnimator.start();
} else {
((AnimatedVectorDrawable) mIconArrowView.getDrawable()).reverse();
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.
mIconTextExpandedView.setRevealClip(true, 0,
mIconTextExpandedView.getHeight() / 2f, 0);
}
});
mAnimator = new AnimatorSet();
mIconTextExpandedView.getWidth(), mIconTextCollapsedView.getWidth());
// Animate background clipping
ValueAnimator backgroundAnimator = ValueAnimator.ofObject(
mBackgroundAnimationRectEvaluator,
initialBackground,
collapsedBackgroundBounds);
backgroundAnimator.addUpdateListener(valueAnimator -> invalidateOutline());
mAnimator.playTogether(
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),
backgroundAnimator,
ObjectAnimator.ofFloat(mIconView, SCALE_PROPERTY, 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));
mAnimator.setDuration(MENU_BACKGROUND_HIDE_DURATION);
mAnimator.setInterpolator(EMPHASIZED);
mAnimator.start();
}
mAnimator.setInterpolator(EMPHASIZED);
mAnimator.start();
}
private Rect getCollapsedBackgroundLtrBounds() {
Rect bounds = new Rect(
0,
0,
Math.min(mMaxWidth, mCollapsedMenuDefaultWidth),
mCollapsedMenuDefaultHeight);
bounds.offset(mBackgroundMarginTopStart, mBackgroundMarginTopStart);
return bounds;
}
private Rect getExpandedBackgroundLtrBounds() {
return new Rect(0, 0, mExpandedMenuDefaultWidth, mExpandedMenuDefaultHeight);
}
protected void reset() {
mIconViewBackgroundCornersStart.setScaleX(1);
mIconViewBackgroundCornersStart.setScaleY(1);
mIconViewBackgroundCornersEnd.setScaleX(1);
mIconViewBackgroundCornersEnd.setScaleY(1);
mIconViewBackgroundCornersEnd.setTranslationX(0);
mIconViewBackground.setScaleX(1);
mIconViewBackground.setScaleY(1);
mBackgroundRelativeLtrLocation.set(getCollapsedBackgroundLtrBounds());
mIconView.setScaleX(1);
mIconView.setScaleY(1);
mIconTextCollapsedView.setTranslationX(0);
@@ -15,8 +15,6 @@
*/
package com.android.quickstep.views;
import static com.android.launcher3.Flags.enableOverviewIconMenu;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -196,10 +194,8 @@ public class IconView extends View implements TaskViewIcon {
setLayoutParams(iconParams);
setRotation(orientationHandler.getDegreesRotated());
int iconDrawableSize = enableOverviewIconMenu()
? deviceProfile.overviewTaskIconAppChipMenuDrawableSizePx
: isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
: deviceProfile.overviewTaskIconDrawableSizePx;
int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
: deviceProfile.overviewTaskIconDrawableSizePx;
setDrawableSize(iconDrawableSize, iconDrawableSize);
}
@@ -225,8 +225,10 @@ public class TaskMenuView extends AbstractFloatingView {
// Get Position
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
mActivity.getDragLayer().getDescendantRectRelativeToSelf(
enableOverviewIconMenu() ? taskContainer.getIconView().asView()
: taskContainer.getThumbnailView(), sTempRect);
enableOverviewIconMenu()
? getIconView().findViewById(R.id.icon_view_menu_anchor)
: taskContainer.getThumbnailView(),
sTempRect);
Rect insets = mActivity.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
params.width = orientationHandler.getTaskMenuWidth(taskContainer.getThumbnailView(),
@@ -246,15 +248,9 @@ public class TaskMenuView extends AbstractFloatingView {
orientationHandler.setTaskOptionsMenuLayoutOrientation(
deviceProfile, mOptionLayout, dividerSpacing, divider);
float thumbnailAlignedX = sTempRect.left - insets.left + (enableOverviewIconMenu()
? -getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_touch_max_margin)
- getResources().getDimension(R.dimen.task_thumbnail_icon_menu_start_margin)
: 0);
float thumbnailAlignedY = sTempRect.top - insets.top + (enableOverviewIconMenu()
? getResources().getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_max_height)
- getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_top_margin) : 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
@@ -262,31 +258,35 @@ public class TaskMenuView extends AbstractFloatingView {
setPivotY(0);
setRotation(orientationHandler.getDegreesRotated());
// Margin that insets the menuView inside the taskView
float taskInsetMarginX = enableOverviewIconMenu() ? getResources().getDimension(
R.dimen.task_thumbnail_icon_menu_start_margin) : getResources().getDimension(
R.dimen.task_card_margin);
float taskInsetMarginY = enableOverviewIconMenu() ? getResources().getDimension(
R.dimen.task_thumbnail_icon_menu_start_margin) : getResources().getDimension(
R.dimen.task_card_margin);
setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX,
mTaskContainer.getThumbnailView(), deviceProfile, taskInsetMarginX,
mTaskContainer.getIconView().asView()));
setTranslationY(orientationHandler.getTaskMenuY(
thumbnailAlignedY, mTaskContainer.getThumbnailView(),
mTaskContainer.getStagePosition(), this, taskInsetMarginY,
mTaskContainer.getIconView().asView()));
if (enableOverviewIconMenu()) {
setTranslationX(thumbnailAlignedX);
setTranslationY(thumbnailAlignedY);
} else {
// 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,
getIconView()));
setTranslationY(orientationHandler.getTaskMenuY(
thumbnailAlignedY, mTaskContainer.getThumbnailView(),
mTaskContainer.getStagePosition(), this, taskInsetMargin,
getIconView()));
}
}
private void animateOpen() {
mMenuTranslationYBeforeOpen = getTranslationY();
mMenuTranslationXBeforeOpen = getTranslationX();
mIconViewTranslationYBeforeOpen = mTaskContainer.getIconView().asView().getTranslationY();
mIconViewTranslationXBeforeOpen = mTaskContainer.getIconView().asView().getTranslationX();
mIconViewTranslationYBeforeOpen = getIconView().getTranslationY();
mIconViewTranslationXBeforeOpen = getIconView().getTranslationX();
animateOpenOrClosed(false);
mIsOpen = true;
}
private View getIconView() {
return mTaskContainer.getIconView().asView();
}
private void animateClose() {
animateOpenOrClosed(true);
}
@@ -318,17 +318,13 @@ public class TaskMenuView extends AbstractFloatingView {
float midpoint = (taskBottom + taskbarTop) / 2f;
additionalTranslationY = -Math.max(menuBottom - midpoint, 0);
}
// Translate the menu to account for the expansion of the app chip menu as well.
float expandOffsetTranslationY = getResources().getDimensionPixelSize(
R.dimen.task_thumbnail_icon_menu_expanded_gap);
ObjectAnimator translationYAnim = ObjectAnimator.ofFloat(this, TRANSLATION_Y,
closing ? mMenuTranslationYBeforeOpen
: mMenuTranslationYBeforeOpen + additionalTranslationY
+ expandOffsetTranslationY);
: mMenuTranslationYBeforeOpen + additionalTranslationY);
translationYAnim.setInterpolator(EMPHASIZED);
ObjectAnimator menuTranslationYAnim = ObjectAnimator.ofFloat(
mTaskContainer.getIconView().asView(), TRANSLATION_Y,
getIconView(), TRANSLATION_Y,
closing ? mIconViewTranslationYBeforeOpen
: mIconViewTranslationYBeforeOpen + additionalTranslationY);
menuTranslationYAnim.setInterpolator(EMPHASIZED);
@@ -349,7 +345,7 @@ public class TaskMenuView extends AbstractFloatingView {
translationXAnim.setInterpolator(EMPHASIZED);
ObjectAnimator menuTranslationXAnim = ObjectAnimator.ofFloat(
mTaskContainer.getIconView().asView(), TRANSLATION_X,
getIconView(), TRANSLATION_X,
closing ? mIconViewTranslationXBeforeOpen
: mIconViewTranslationXBeforeOpen - additionalTranslationX);
menuTranslationXAnim.setInterpolator(EMPHASIZED);
@@ -393,7 +389,7 @@ public class TaskMenuView extends AbstractFloatingView {
if (enableOverviewIconMenu()) {
((IconAppChipView) mTaskContainer.getIconView()).reset();
setTranslationY(mMenuTranslationYBeforeOpen);
mTaskContainer.getIconView().asView().setTranslationY(mIconViewTranslationYBeforeOpen);
getIconView().setTranslationY(mIconViewTranslationYBeforeOpen);
}
}