Handle page offset for grid overview
- Use TaskView's actual position with grid/fullscreen translation considered for taskPosition calculation
- Shift taskPosition by midpoint scroll, and no longer assumes midpoint is on middle of the screen
- Handle situation that TaskView is on left/right of midpoint, making the calculation generic to be able to handle grid situation
Bug: 175939487
Test: Launch modal view with wide/, RTL/non-RTL, orientation/simulated landscape combinations
Change-Id: Idd0cc9c5e24f453d830e1420319a38d3d784270d
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5d3e0b8..1df3d3c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -270,7 +270,8 @@
public void setValue(RecentsView view, float scale) {
view.setScaleX(scale);
view.setScaleY(scale);
- view.mLastComputedTaskPushOutDistance = null;
+ view.mLastComputedTaskStartPushOutDistance = null;
+ view.mLastComputedTaskEndPushOutDistance = null;
view.mLiveTileTaskViewSimulator.recentsViewScale.value = scale;
view.updatePageOffsets();
view.setTaskViewsResistanceTranslation(view.mTaskViewsSecondaryTranslation);
@@ -308,7 +309,8 @@
protected final Rect mLastComputedGridSize = new Rect();
protected final Rect mLastComputedGridTaskSize = new Rect();
// How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
- protected Float mLastComputedTaskPushOutDistance = null;
+ protected Float mLastComputedTaskStartPushOutDistance = null;
+ protected Float mLastComputedTaskEndPushOutDistance = null;
protected boolean mEnableDrawingLiveTile = false;
protected final Rect mTempRect = new Rect();
protected final RectF mTempRectF = new RectF();
@@ -2467,7 +2469,8 @@
setPivotX(mTempPointF.x);
setPivotY(mTempPointF.y);
setTaskModalness(mTaskModalness);
- mLastComputedTaskPushOutDistance = null;
+ mLastComputedTaskStartPushOutDistance = null;
+ mLastComputedTaskEndPushOutDistance = null;
updatePageOffsets();
setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
@@ -2476,10 +2479,6 @@
private void updatePageOffsets() {
float offset = mAdjacentPageOffset;
float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness);
- if (mIsRtl) {
- offset = -offset;
- modalOffset = -modalOffset;
- }
int count = getChildCount();
TaskView runningTask = mRunningTaskId == -1 || !mRunningTaskTileHidden
@@ -2495,13 +2494,27 @@
? getOffsetSize(midpoint + 1, midpoint, offset)
: 0;
+ boolean showAsGrid = showAsGrid();
float modalMidpointOffsetSize = 0;
- float modalLeftOffsetSize = modalMidpoint - 1 >= 0
- ? -getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset)
- : 0;
- float modalRightOffsetSize = modalMidpoint + 1 < count
- ? getOffsetSize(modalMidpoint + 1, modalMidpoint, modalOffset)
- : 0;
+ float modalLeftOffsetSize = 0;
+ float modalRightOffsetSize = 0;
+ float gridOffsetSize = 0;
+
+ if (showAsGrid) {
+ // In grid, we only focus the task on the side. The reference index used for offset
+ // calculation is the task directly next to the focus task in the grid.
+ int referenceIndex = modalMidpoint == 0 ? 1 : 0;
+ gridOffsetSize = referenceIndex < count
+ ? getOffsetSize(referenceIndex, modalMidpoint, modalOffset)
+ : 0;
+ } else {
+ modalLeftOffsetSize = modalMidpoint - 1 >= 0
+ ? getOffsetSize(modalMidpoint - 1, modalMidpoint, modalOffset)
+ : 0;
+ modalRightOffsetSize = modalMidpoint + 1 < count
+ ? getOffsetSize(modalMidpoint + 1, modalMidpoint, modalOffset)
+ : 0;
+ }
for (int i = 0; i < count; i++) {
float translation = i == midpoint
@@ -2511,21 +2524,37 @@
: rightOffsetSize;
float modalTranslation = i == modalMidpoint
? modalMidpointOffsetSize
- : i < modalMidpoint
- ? modalLeftOffsetSize
- : modalRightOffsetSize;
+ : showAsGrid
+ ? gridOffsetSize
+ : i < modalMidpoint ? modalLeftOffsetSize : modalRightOffsetSize;
float totalTranslation = translation + modalTranslation;
View child = getChildAt(i);
FloatProperty translationProperty = child instanceof TaskView
? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
: mOrientationHandler.getPrimaryViewTranslate();
- translationProperty.set(child,
- totalTranslation * mOrientationHandler.getPrimaryTranslationDirectionFactor());
+ translationProperty.set(child, totalTranslation);
}
updateCurveProperties();
}
/**
+ * Computes the child position with persistent translation considered (see
+ * {@link TaskView#getPersistentTranslationX()}.
+ */
+ private void getPersistentChildPosition(int childIndex, int midPointScroll, RectF outRect) {
+ View child = getChildAt(childIndex);
+ outRect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
+ if (child instanceof TaskView) {
+ TaskView taskView = (TaskView) child;
+ outRect.offset(taskView.getPersistentTranslationX(),
+ taskView.getPersistentTranslationY());
+ outRect.top += mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+ }
+ outRect.offset(mOrientationHandler.getPrimaryValue(-midPointScroll, 0),
+ mOrientationHandler.getSecondaryValue(-midPointScroll, 0));
+ }
+
+ /**
* Computes the distance to offset the given child such that it is completely offscreen when
* translating away from the given midpoint.
* @param offsetProgress From 0 to 1 where 0 means no offset and 1 means offset offscreen.
@@ -2535,33 +2564,60 @@
// Don't bother calculating everything below if we won't offset anyway.
return 0;
}
+
// First, get the position of the task relative to the midpoint. If there is no midpoint
// then we just use the normal (centered) task position.
- mTempRectF.set(mLastComputedTaskSize);
RectF taskPosition = mTempRectF;
- float desiredLeft = getWidth();
- // Used to calculate the scale of the task view based on its new offset.
+ // Whether the task should be shifted to start direction (i.e. left edge for portrait, top
+ // edge for landscape/seascape).
+ boolean isStartShift;
if (midpointIndex > -1) {
// When there is a midpoint reference task, adjacent tasks have less distance to travel
// to reach offscreen. Offset the task position to the task's starting point.
- View child = getChildAt(childIndex);
- View midpointChild = getChildAt(midpointIndex);
- int distanceFromMidpoint = Math.abs(mOrientationHandler.getChildStart(child)
- - mOrientationHandler.getChildStart(midpointChild)
- + getDisplacementFromScreenCenter(midpointIndex));
- taskPosition.offset(distanceFromMidpoint, 0);
+ int midpointScroll = getScrollForPage(midpointIndex);
+ getPersistentChildPosition(midpointIndex, midpointScroll, taskPosition);
+ float midpointStart = mOrientationHandler.getStart(taskPosition);
+
+ getPersistentChildPosition(childIndex, midpointScroll, taskPosition);
+ // Assume child does not overlap with midPointChild.
+ isStartShift = mOrientationHandler.getStart(taskPosition) < midpointStart;
+ } else {
+ // Position the task at scroll position.
+ getPersistentChildPosition(childIndex, getScrollForPage(childIndex), taskPosition);
+ isStartShift = mIsRtl;
}
- float distanceToOffscreen = desiredLeft - taskPosition.left;
- // Finally, we need to account for RecentsView scale, because it moves tasks based on its
- // pivot. To do this, we move the task position to where it would be offscreen at scale = 1
- // (computed above), then we apply the scale via getMatrix() to determine how much that
- // moves the task from its desired position, and adjust the computed distance accordingly.
- if (mLastComputedTaskPushOutDistance == null) {
- taskPosition.offsetTo(desiredLeft, 0);
- getMatrix().mapRect(taskPosition);
- mLastComputedTaskPushOutDistance = (taskPosition.left - desiredLeft) / getScaleX();
+
+ // Next, calculate the distance to move the task off screen. We also need to account for
+ // RecentsView scale, because it moves tasks based on its pivot. To do this, we move the
+ // task position to where it would be offscreen at scale = 1 (computed above), then we
+ // apply the scale via getMatrix() to determine how much that moves the task from its
+ // desired position, and adjust the computed distance accordingly.
+ float distanceToOffscreen;
+ if (isStartShift) {
+ float desiredStart = -mOrientationHandler.getPrimarySize(taskPosition);
+ distanceToOffscreen = -mOrientationHandler.getEnd(taskPosition);
+ if (mLastComputedTaskStartPushOutDistance == null) {
+ taskPosition.offsetTo(
+ mOrientationHandler.getPrimaryValue(desiredStart, 0f),
+ mOrientationHandler.getSecondaryValue(desiredStart, 0f));
+ getMatrix().mapRect(taskPosition);
+ mLastComputedTaskStartPushOutDistance = mOrientationHandler.getEnd(taskPosition)
+ / mOrientationHandler.getPrimaryScale(this);
+ }
+ distanceToOffscreen -= mLastComputedTaskStartPushOutDistance;
+ } else {
+ float desiredStart = mOrientationHandler.getPrimarySize(this);
+ distanceToOffscreen = desiredStart - mOrientationHandler.getStart(taskPosition);
+ if (mLastComputedTaskEndPushOutDistance == null) {
+ taskPosition.offsetTo(
+ mOrientationHandler.getPrimaryValue(desiredStart, 0f),
+ mOrientationHandler.getSecondaryValue(desiredStart, 0f));
+ getMatrix().mapRect(taskPosition);
+ mLastComputedTaskEndPushOutDistance = (mOrientationHandler.getStart(taskPosition)
+ - desiredStart) / mOrientationHandler.getPrimaryScale(this);
+ }
+ distanceToOffscreen -= mLastComputedTaskEndPushOutDistance;
}
- distanceToOffscreen -= mLastComputedTaskPushOutDistance;
return distanceToOffscreen * offsetProgress;
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index e6143fb..8f22622 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -987,20 +987,30 @@
private void applyTranslationX() {
setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
- + getFullscreenTrans(mFullscreenTranslationX)
- + getNonFullscreenTrans(mNonFullscreenTranslationX)
- + getGridTrans(mGridTranslationX));
+ + getPersistentTranslationX());
}
private void applyTranslationY() {
- setTranslationY(
- mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
- + getGridTrans(mGridTranslationY) + mBoxTranslationY);
+ setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
+ + getPersistentTranslationY());
}
- private float getGridTrans(float endTranslation) {
- float progress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
- return Utilities.mapRange(progress, 0, endTranslation);
+ /**
+ * Returns addition of translationX that is persistent (e.g. fullscreen and grid), and does not
+ * change according to a temporary state (e.g. task offset).
+ */
+ public float getPersistentTranslationX() {
+ return getFullscreenTrans(mFullscreenTranslationX)
+ + getNonFullscreenTrans(mNonFullscreenTranslationX)
+ + getGridTrans(mGridTranslationX);
+ }
+
+ /**
+ * Returns addition of translationY that is persistent (e.g. fullscreen and grid), and does not
+ * change according to a temporary state (e.g. task offset).
+ */
+ public float getPersistentTranslationY() {
+ return getGridTrans(mGridTranslationY) + mBoxTranslationY;
}
public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
@@ -1275,6 +1285,11 @@
return endTranslation - getFullscreenTrans(endTranslation);
}
+ private float getGridTrans(float endTranslation) {
+ float progress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
+ return Utilities.mapRange(progress, 0, endTranslation);
+ }
+
public boolean isRunningTask() {
if (getRecentsView() == null) {
return false;
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index a241e63..18e27a4 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -122,11 +122,26 @@
}
@Override
+ public int getPrimarySize(View view) {
+ return view.getHeight();
+ }
+
+ @Override
public float getPrimarySize(RectF rect) {
return rect.height();
}
@Override
+ public float getStart(RectF rect) {
+ return rect.top;
+ }
+
+ @Override
+ public float getEnd(RectF rect) {
+ return rect.bottom;
+ }
+
+ @Override
public int getClearAllSidePadding(View view, boolean isRtl) {
return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2;
}
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index b85d08a..560df86 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -65,7 +65,10 @@
float getPrimaryDirection(MotionEvent event, int pointerIndex);
float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId);
int getMeasuredSize(View view);
+ int getPrimarySize(View view);
float getPrimarySize(RectF rect);
+ float getStart(RectF rect);
+ float getEnd(RectF rect);
int getClearAllSidePadding(View view, boolean isRtl);
int getSecondaryDimension(View view);
FloatProperty<View> getPrimaryViewTranslate();
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 2fb5952..86508c4 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -118,11 +118,26 @@
}
@Override
+ public int getPrimarySize(View view) {
+ return view.getWidth();
+ }
+
+ @Override
public float getPrimarySize(RectF rect) {
return rect.width();
}
@Override
+ public float getStart(RectF rect) {
+ return rect.left;
+ }
+
+ @Override
+ public float getEnd(RectF rect) {
+ return rect.right;
+ }
+
+ @Override
public int getClearAllSidePadding(View view, boolean isRtl) {
return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2;
}