Merge "open grid task menu to the right of icon" into sc-v2-dev
This commit is contained in:
commit
bd1aec6721
|
@ -28,6 +28,7 @@
|
|||
<dimen name="task_menu_item_corner_radius">4dp</dimen>
|
||||
<dimen name="task_menu_spacing">2dp</dimen>
|
||||
<dimen name="task_menu_width_grid">234dp</dimen>
|
||||
<dimen name="task_menu_horizontal_padding">8dp</dimen>
|
||||
<dimen name="overview_proactive_row_height">48dp</dimen>
|
||||
<dimen name="overview_proactive_row_bottom_margin">16dp</dimen>
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ public class KtR {
|
|||
|
||||
public static final class dimen {
|
||||
public static int task_menu_spacing = R.dimen.task_menu_spacing;
|
||||
public static int task_menu_horizontal_padding = R.dimen.task_menu_horizontal_padding;
|
||||
}
|
||||
|
||||
public static final class layout {
|
||||
|
|
|
@ -23,14 +23,18 @@ import android.graphics.Rect
|
|||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.graphics.drawable.shapes.RectShape
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import com.android.launcher3.BaseDraggingActivity
|
||||
import com.android.launcher3.DeviceProfile
|
||||
import com.android.launcher3.InsettableFrameLayout
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.popup.ArrowPopup
|
||||
import com.android.launcher3.popup.RoundedArrowDrawable
|
||||
import com.android.launcher3.popup.SystemShortcut
|
||||
import com.android.launcher3.util.Themes
|
||||
import com.android.quickstep.KtR
|
||||
|
@ -43,9 +47,13 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
|||
|
||||
fun showForTask(taskContainer: TaskIdAttributeContainer): Boolean {
|
||||
val activity = BaseDraggingActivity
|
||||
.fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
|
||||
.fromContext<BaseDraggingActivity>(taskContainer.taskView.context)
|
||||
val taskMenuViewWithArrow = activity.layoutInflater
|
||||
.inflate(KtR.layout.task_menu_with_arrow, activity.dragLayer, false) as TaskMenuViewWithArrow<*>
|
||||
.inflate(
|
||||
KtR.layout.task_menu_with_arrow,
|
||||
activity.dragLayer,
|
||||
false
|
||||
) as TaskMenuViewWithArrow<*>
|
||||
|
||||
return taskMenuViewWithArrow.populateAndShowForTask(taskContainer)
|
||||
}
|
||||
|
@ -53,10 +61,21 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
|||
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
init {
|
||||
clipToOutline = true
|
||||
|
||||
shouldScaleArrow = true
|
||||
// This synchronizes the arrow and menu to open at the same time
|
||||
OPEN_CHILD_FADE_START_DELAY = OPEN_FADE_START_DELAY
|
||||
OPEN_CHILD_FADE_DURATION = OPEN_FADE_DURATION
|
||||
CLOSE_FADE_START_DELAY = CLOSE_CHILD_FADE_START_DELAY
|
||||
CLOSE_FADE_DURATION = CLOSE_CHILD_FADE_DURATION
|
||||
}
|
||||
|
||||
private val menuWidth = context.resources.getDimensionPixelSize(R.dimen.task_menu_width_grid)
|
||||
|
@ -65,6 +84,13 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
|||
private lateinit var optionLayout: LinearLayout
|
||||
private lateinit var taskContainer: TaskIdAttributeContainer
|
||||
|
||||
private var optionMeasuredHeight = 0
|
||||
private val arrowHorizontalPadding: Int
|
||||
get() = if (taskView.isFocusedTask)
|
||||
resources.getDimensionPixelSize(KtR.dimen.task_menu_horizontal_padding)
|
||||
else
|
||||
0
|
||||
|
||||
override fun isOfType(type: Int): Boolean = type and TYPE_TASK_MENU != 0
|
||||
|
||||
override fun getTargetObjectLocation(outPos: Rect?) {
|
||||
|
@ -147,7 +173,10 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
|||
}
|
||||
|
||||
override fun assignMarginsAndBackgrounds(viewGroup: ViewGroup) {
|
||||
assignMarginsAndBackgrounds(this, Themes.getAttrColor(context, com.android.internal.R.attr.colorSurface))
|
||||
assignMarginsAndBackgrounds(
|
||||
this,
|
||||
Themes.getAttrColor(context, com.android.internal.R.attr.colorSurface)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateOpenAnimation(anim: AnimatorSet) {
|
||||
|
@ -164,4 +193,90 @@ class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
|
|||
ObjectAnimator.ofFloat(taskContainer.thumbnailView, TaskThumbnailView.DIM_ALPHA, 0f)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Orients this container to the left or right of the given icon, aligning with the first option
|
||||
* or second.
|
||||
*
|
||||
* These are the preferred orientations, in order (RTL prefers right-aligned over left):
|
||||
* - Right and first option aligned
|
||||
* - Right and second option aligned
|
||||
* - Left and first option aligned
|
||||
* - Left and second option aligned
|
||||
*
|
||||
* So we always align right if there is enough horizontal space
|
||||
*/
|
||||
override fun orientAboutObject() {
|
||||
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
|
||||
// Needed for offsets later
|
||||
optionMeasuredHeight = optionLayout.getChildAt(0).measuredHeight
|
||||
val extraHorizontalSpace = (mArrowHeight + mArrowOffsetVertical + arrowHorizontalPadding)
|
||||
|
||||
val widthWithArrow = measuredWidth + paddingLeft + paddingRight + extraHorizontalSpace
|
||||
getTargetObjectLocation(mTempRect)
|
||||
val dragLayer: InsettableFrameLayout = popupContainer
|
||||
val insets = dragLayer.insets
|
||||
|
||||
// Put to the right of the icon if there is space, which means left aligned with the menu
|
||||
val rightAlignedMenuStartX = mTempRect.left - widthWithArrow
|
||||
val leftAlignedMenuStartX = mTempRect.right + extraHorizontalSpace
|
||||
mIsLeftAligned = if (mIsRtl) {
|
||||
rightAlignedMenuStartX + insets.left < 0
|
||||
} else {
|
||||
leftAlignedMenuStartX + (widthWithArrow - extraHorizontalSpace) + insets.left <
|
||||
dragLayer.width - insets.right
|
||||
}
|
||||
|
||||
var menuStartX = if (mIsLeftAligned) leftAlignedMenuStartX else rightAlignedMenuStartX
|
||||
|
||||
// Offset y so that the arrow and first row are center-aligned with the original icon.
|
||||
val iconHeight = mTempRect.height()
|
||||
val optionHeight = optionMeasuredHeight
|
||||
val yOffset = (optionHeight - iconHeight) / 2
|
||||
var menuStartY = mTempRect.top - yOffset
|
||||
|
||||
// Insets are added later, so subtract them now.
|
||||
menuStartX -= insets.left
|
||||
menuStartY -= insets.top
|
||||
|
||||
setX(menuStartX.toFloat())
|
||||
setY(menuStartY.toFloat())
|
||||
|
||||
val lp = layoutParams as FrameLayout.LayoutParams
|
||||
val arrowLp = mArrow.layoutParams as FrameLayout.LayoutParams
|
||||
lp.gravity = Gravity.TOP
|
||||
arrowLp.gravity = lp.gravity
|
||||
}
|
||||
|
||||
override fun addArrow() {
|
||||
popupContainer.addView(mArrow)
|
||||
mArrow.x = getArrowX()
|
||||
mArrow.y = y + (optionMeasuredHeight / 2) - (mArrowHeight / 2)
|
||||
|
||||
updateArrowColor()
|
||||
|
||||
// This is inverted (x = height, y = width) because the arrow is rotated
|
||||
mArrow.pivotX = if (mIsLeftAligned) 0f else mArrowHeight.toFloat()
|
||||
mArrow.pivotY = 0f
|
||||
}
|
||||
|
||||
private fun getArrowX(): Float {
|
||||
return if (mIsLeftAligned)
|
||||
x - mArrowHeight
|
||||
else
|
||||
x + measuredWidth + mArrowOffsetVertical
|
||||
}
|
||||
|
||||
override fun updateArrowColor() {
|
||||
mArrow.background = RoundedArrowDrawable(
|
||||
mArrowWidth.toFloat(),
|
||||
mArrowHeight.toFloat(),
|
||||
mArrowPointRadius.toFloat(),
|
||||
mIsLeftAligned,
|
||||
mArrowColor
|
||||
)
|
||||
elevation = mElevation
|
||||
mArrow.elevation = mElevation
|
||||
}
|
||||
|
||||
}
|
|
@ -77,44 +77,45 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
|||
extends AbstractFloatingView {
|
||||
|
||||
// Duration values (ms) for popup open and close animations.
|
||||
private static final int OPEN_DURATION = 276;
|
||||
private static final int OPEN_FADE_START_DELAY = 0;
|
||||
private static final int OPEN_FADE_DURATION = 38;
|
||||
private static final int OPEN_CHILD_FADE_START_DELAY = 38;
|
||||
private static final int OPEN_CHILD_FADE_DURATION = 76;
|
||||
protected int OPEN_DURATION = 276;
|
||||
protected int OPEN_FADE_START_DELAY = 0;
|
||||
protected int OPEN_FADE_DURATION = 38;
|
||||
protected int OPEN_CHILD_FADE_START_DELAY = 38;
|
||||
protected int OPEN_CHILD_FADE_DURATION = 76;
|
||||
|
||||
private static final int CLOSE_DURATION = 200;
|
||||
private static final int CLOSE_FADE_START_DELAY = 140;
|
||||
private static final int CLOSE_FADE_DURATION = 50;
|
||||
private static final int CLOSE_CHILD_FADE_START_DELAY = 0;
|
||||
private static final int CLOSE_CHILD_FADE_DURATION = 140;
|
||||
protected int CLOSE_DURATION = 200;
|
||||
protected int CLOSE_FADE_START_DELAY = 140;
|
||||
protected int CLOSE_FADE_DURATION = 50;
|
||||
protected int CLOSE_CHILD_FADE_START_DELAY = 0;
|
||||
protected int CLOSE_CHILD_FADE_DURATION = 140;
|
||||
|
||||
// Index used to get background color when using local wallpaper color extraction,
|
||||
private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_neutral2_800;
|
||||
private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
protected final Rect mTempRect = new Rect();
|
||||
|
||||
protected final LayoutInflater mInflater;
|
||||
private final float mOutlineRadius;
|
||||
protected final float mOutlineRadius;
|
||||
protected final T mActivityContext;
|
||||
protected final boolean mIsRtl;
|
||||
|
||||
private final int mArrowOffsetVertical;
|
||||
private final int mArrowOffsetHorizontal;
|
||||
private final int mArrowWidth;
|
||||
private final int mArrowHeight;
|
||||
private final int mArrowPointRadius;
|
||||
private final View mArrow;
|
||||
protected final int mArrowOffsetVertical;
|
||||
protected final int mArrowOffsetHorizontal;
|
||||
protected final int mArrowWidth;
|
||||
protected final int mArrowHeight;
|
||||
protected final int mArrowPointRadius;
|
||||
protected final View mArrow;
|
||||
|
||||
private final int mMargin;
|
||||
|
||||
protected boolean mIsLeftAligned;
|
||||
protected boolean mIsAboveIcon;
|
||||
private int mGravity;
|
||||
protected int mGravity;
|
||||
|
||||
protected AnimatorSet mOpenCloseAnimator;
|
||||
protected boolean mDeferContainerRemoval;
|
||||
protected boolean shouldScaleArrow = false;
|
||||
|
||||
private final GradientDrawable mRoundedTop;
|
||||
private final GradientDrawable mRoundedBottom;
|
||||
|
@ -122,10 +123,10 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
|||
private Runnable mOnCloseCallback = () -> { };
|
||||
|
||||
// The rect string of the view that the arrow is attached to, in screen reference frame.
|
||||
private int mArrowColor;
|
||||
protected int mArrowColor;
|
||||
protected final List<LocalColorExtractor> mColorExtractors;
|
||||
|
||||
private final float mElevation;
|
||||
protected final float mElevation;
|
||||
private final int mBackgroundColor;
|
||||
|
||||
private final String mIterateChildrenTag;
|
||||
|
@ -729,6 +730,14 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
|
|||
scale.setInterpolator(interpolator);
|
||||
animatorSet.play(scale);
|
||||
|
||||
if (shouldScaleArrow) {
|
||||
Animator arrowScaleAnimator = ObjectAnimator.ofFloat(mArrow, View.SCALE_Y,
|
||||
scaleValues);
|
||||
arrowScaleAnimator.setDuration(totalDuration);
|
||||
arrowScaleAnimator.setInterpolator(interpolator);
|
||||
animatorSet.play(arrowScaleAnimator);
|
||||
}
|
||||
|
||||
fadeInChildViews(this, alphaValues, childFadeStartDelay, childFadeDuration, animatorSet);
|
||||
|
||||
return animatorSet;
|
||||
|
|
|
@ -78,6 +78,32 @@ public class RoundedArrowDrawable extends Drawable {
|
|||
mPath.transform(pathTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an arrow that points to the left or right.
|
||||
*
|
||||
* @param width of the arrow.
|
||||
* @param height of the arrow.
|
||||
* @param radius of the tip of the arrow.
|
||||
* @param isPointingLeft or not.
|
||||
* @param color to draw the triangle.
|
||||
*/
|
||||
public RoundedArrowDrawable(float width, float height, float radius, boolean isPointingLeft,
|
||||
int color) {
|
||||
mPath = new Path();
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(color);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setAntiAlias(true);
|
||||
|
||||
// Make the drawable with the triangle pointing down...
|
||||
addDownPointingRoundedTriangleToPath(width, height, radius, mPath);
|
||||
|
||||
// ... then rotate it to the side it needs to point.
|
||||
Matrix pathTransform = new Matrix();
|
||||
pathTransform.setRotate(isPointingLeft ? 90 : -90, width * 0.5f, height * 0.5f);
|
||||
mPath.transform(pathTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawPath(mPath, mPaint);
|
||||
|
|
Loading…
Reference in New Issue