Enable variable size thumbnail for large screen

- Introduced a feature flag
- Refresh TaskView size when thumbnail is refreshed or Recents resizes
- Disable edge scale down in large screens
- Added temp method to get task width/height ratio
- In fullscreen, scale down TaskThumbnailView and disable TaskView elevation
- Task boxing mechanism: http://screen/3NkePthAVUVH2Rv.png

Bug: 174464656
Test: Manually test overview and quickswitch for folded and unfolded, including with RTL.
Change-Id: I2ce24d588a246cc6a2408039a37d884021aa0800
This commit is contained in:
Alex Chau
2021-02-08 19:40:49 +00:00
parent fd03d04ae0
commit 7944ee5c79
8 changed files with 361 additions and 57 deletions
@@ -32,6 +32,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
@@ -150,9 +151,11 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
mTaskBeingDragged = view;
int upDirection = mRecentsView.getPagedOrientationHandler()
.getUpDirection(mIsRtl);
if (!SysUINavigationMode.getMode(mActivity).hasGestures) {
if (!SysUINavigationMode.getMode(mActivity).hasGestures || (
mActivity.getDeviceProfile().isTablet
&& FeatureFlags.ENABLE_OVERVIEW_GRID.get())) {
// Don't allow swipe down to open if we don't support swipe up
// to enter overview.
// to enter overview, or when grid layout is enabled.
directionsToDetectScroll = upDirection;
mAllowGoingUp = true;
mAllowGoingDown = false;
@@ -49,6 +49,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager;
@@ -174,11 +175,13 @@ public final class TaskViewUtils {
final RecentsView recentsView = v.getRecentsView();
int taskIndex = recentsView.indexOfChild(v);
boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage();
int startScroll = recentsView.getScrollOffset(taskIndex);
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
boolean parallaxCenterAndAdjacentTask =
taskIndex != recentsView.getCurrentPage() && !(dp.isTablet
&& FeatureFlags.ENABLE_OVERVIEW_GRID.get());
int startScroll = recentsView.getScrollOffset(taskIndex);
TaskViewSimulator topMostSimulator = null;
if (tsv == null && targets.apps.length > 0) {
@@ -276,8 +276,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
int start = mOrientationState.getOrientationHandler()
.getPrimaryValue(mTaskRect.left, mTaskRect.top);
mScrollState.screenCenter = start + mScrollState.scroll + mScrollState.halfPageSize;
mScrollState.updateInterpolation(start);
mCurveScale = TaskView.getCurveScaleForInterpolation(mScrollState.linearInterpolation);
mScrollState.updateInterpolation(mDp, start);
mCurveScale = TaskView.getCurveScaleForInterpolation(mDp,
mScrollState.linearInterpolation);
}
float progress = Utilities.boundToRange(fullScreenProgress.value, 0, 1);
@@ -898,9 +898,14 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
public void setFullscreenProgress(float fullscreenProgress) {
mFullscreenProgress = fullscreenProgress;
int taskCount = getTaskViewCount();
float accumulatedTranslationX = 0;
for (int i = 0; i < taskCount; i++) {
getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress);
TaskView taskView = getTaskViewAt(i);
taskView.setFullscreenProgress(mFullscreenProgress);
taskView.setAccumulatedTranslationX(accumulatedTranslationX);
accumulatedTranslationX += taskView.getFullscreenTranslationX();
}
// Fade out the actions view quickly (0.1 range)
mActionsView.getFullscreenAlpha().setValue(
mapToRange(fullscreenProgress, 0, 0.1f, 1f, 0f, LINEAR));
@@ -934,6 +939,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.widthPx - mInsets.right - mTempRect.right,
dp.heightPx - mInsets.bottom - mTempRect.bottom);
// Force TaskView to update size from thumbnail
final int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
getTaskViewAt(i).updateTaskSize();
}
}
public void getTaskSize(Rect outRect) {
@@ -942,6 +952,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mLastComputedTaskSize.set(outRect);
}
/** Gets the last computed task size */
public Rect getLastComputedTaskSize() {
return mLastComputedTaskSize;
}
/** Gets the task size for modal state. */
public void getModalTaskSize(Rect outRect) {
mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
@@ -987,7 +1002,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
final int pageCount = getPageCount();
for (int i = 0; i < pageCount; i++) {
View page = getPageAt(i);
mScrollState.updateInterpolation(
mScrollState.updateInterpolation(mActivity.getDeviceProfile(),
mOrientationHandler.getChildStartWithTranslation(page));
((PageCallbacks) page).onPageScroll(mScrollState);
}
@@ -1422,13 +1437,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
/**
* Updates linearInterpolation for the provided child position
*/
public void updateInterpolation(float childStart) {
public void updateInterpolation(DeviceProfile deviceProfile, float childStart) {
float pageCenter = childStart + halfPageSize;
float distanceFromScreenCenter = screenCenter - pageCenter;
// How far the page has to move from the center to be offscreen, taking into account
// the EDGE_SCALE_DOWN_FACTOR that will be applied at that position.
float distanceToReachEdge = halfScreenSize
+ halfPageSize * (1 - TaskView.EDGE_SCALE_DOWN_FACTOR);
+ halfPageSize * (1 - TaskView.getEdgeScaleDownFactor(deviceProfile));
linearInterpolation = Math.min(1,
Math.abs(distanceFromScreenCenter) / distanceToReachEdge);
}
@@ -1444,12 +1459,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
}
}
private void addDismissedTaskAnimations(View taskView, long duration, PendingAnimation anim) {
private void addDismissedTaskAnimations(TaskView taskView, long duration,
PendingAnimation anim) {
// Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
// alpha is set to 0 so that it can be recycled in the view pool properly
anim.setFloat(taskView, VIEW_ALPHA, 0, ACCEL_2);
FloatProperty<View> secondaryViewTranslate =
mOrientationHandler.getSecondaryViewTranslate();
FloatProperty<TaskView> secondaryViewTranslate =
taskView.getDismissTaskTranslationProperty();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
int verticalFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
@@ -1515,7 +1531,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
if (scrollDiff != 0) {
FloatProperty translationProperty = child instanceof TaskView
? ((TaskView) child).getPrimaryFillDismissGapTranslationProperty()
? ((TaskView) child).getFillDismissGapTranslationProperty()
: mOrientationHandler.getPrimaryViewTranslate();
ResourceProvider rp = DynamicResource.provider(mActivity);
@@ -1971,7 +1987,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
// Find the task's scale based on its offscreen progress, then see how far it still needs to
// move to be completely offscreen.
Utilities.scaleRectFAboutCenter(taskPosition,
TaskView.getCurveScaleForInterpolation(centerToOffscreenProgress));
TaskView.getCurveScaleForInterpolation(mActivity.getDeviceProfile(),
centerToOffscreenProgress));
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
@@ -1990,7 +2007,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
mTaskViewsSecondaryTranslation = translation;
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView task = getTaskViewAt(i);
mOrientationHandler.getSecondaryViewTranslate().set(task, translation / getScaleY());
task.getTaskResistanceTranslationProperty().set(task, translation / getScaleY());
}
mLiveTileTaskViewSimulator.recentsViewSecondaryTranslation.value = translation;
}
@@ -2358,6 +2375,52 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
return super.computeMinScroll();
}
@Override
protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren,
ComputePageScrollsLogic scrollLogic) {
boolean pageScrollChanged = super.getPageScrolls(outPageScrolls, layoutChildren,
scrollLogic);
final int taskCount = getTaskViewCount();
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
if (childCount < mTaskViewStartIndex) {
continue;
}
final TaskView taskView = getTaskViewAt(
Utilities.boundToRange(i, mTaskViewStartIndex, taskCount - 1));
float scrollDiff =
taskView.getFullscreenTranslationX() + taskView.getAccumulatedTranslationX();
if (scrollDiff != 0) {
outPageScrolls[i] += scrollDiff;
pageScrollChanged = true;
}
}
return pageScrollChanged;
}
@Override
protected int getChildOffset(int index) {
if (index < mTaskViewStartIndex) {
return super.getChildOffset(index);
}
final TaskView taskView = getTaskViewAt(
Utilities.boundToRange(index, mTaskViewStartIndex, getTaskViewCount() - 1));
return super.getChildOffset(index) + (int) taskView.getFullscreenTranslationX()
+ (int) taskView.getAccumulatedTranslationX();
}
@Override
protected int getChildVisibleSize(int index) {
final TaskView taskView = getTaskViewAtByAbsoluteIndex(index);
if (taskView == null) {
return super.getChildVisibleSize(index);
}
return super.getChildVisibleSize(index) - (int) taskView.getFullscreenTranslationX();
}
@Override
protected int computeMaxScroll() {
if (getTaskViewCount() > 0) {
@@ -51,6 +51,7 @@ import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SystemUiController;
@@ -110,6 +111,9 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
private boolean mOverlayEnabled;
private OverviewScreenshotActions mOverviewScreenshotActionsPlugin;
// TODO(b/179466077): Remove when proper API is ready.
private Float mThumbnailRatio = null;
public TaskThumbnailView(Context context) {
this(context, null);
}
@@ -450,6 +454,31 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
return mThumbnailData.isRealSnapshot;
}
// TODO(b/179466077): Remove when proper API is ready.
public float getThumbnailRatio() {
// API is ready.
if (mThumbnailRatio != null) {
return mThumbnailRatio;
}
if (mThumbnailData == null || mThumbnailData.thumbnail == null) {
final float[] thumbnailRatios =
new float[]{0.8882452f, 1.2834098f, 0.5558415f, 2.15625f};
// Use key's hash code to return a deterministic thumbnail ratio.
mThumbnailRatio = thumbnailRatios[mTask.key.hashCode() % thumbnailRatios.length];
return mThumbnailRatio;
}
float surfaceWidth = mThumbnailData.thumbnail.getWidth() / mThumbnailData.scale;
float surfaceHeight = mThumbnailData.thumbnail.getHeight() / mThumbnailData.scale;
float availableWidth = surfaceWidth
- (mThumbnailData.insets.left + mThumbnailData.insets.right);
float availableHeight = surfaceHeight
- (mThumbnailData.insets.top + mThumbnailData.insets.bottom);
mThumbnailRatio = availableWidth / availableHeight;
return mThumbnailRatio;
}
/**
* Utility class to position the thumbnail in the TaskView
*/
@@ -480,9 +509,11 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
float scale = thumbnailData.scale;
final float thumbnailScale;
// Landscape vs portrait change
// Landscape vs portrait change.
// Note: Disable rotation in grid layout.
boolean windowingModeSupportsRotation = !dp.isMultiWindowMode
&& thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN;
&& thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN
&& !(dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get());
isOrientationDifferent = isOrientationChange(deltaRotate)
&& windowingModeSupportsRotation;
if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
@@ -30,6 +30,8 @@ import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
@@ -61,6 +63,7 @@ import android.view.MotionEvent;
import android.view.Surface;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -72,6 +75,7 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -120,10 +124,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
*/
public static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
/**
* How much to scale down pages near the edge of the screen.
*/
public static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
private static final float EDGE_SCALE_DOWN_FACTOR_CAROUSEL = 0.03f;
private static final float EDGE_SCALE_DOWN_FACTOR_GRID = 0.00f;
public static final long SCALE_ICON_DURATION = 120;
private static final long DIM_ANIM_DURATION = 700;
@@ -152,29 +154,29 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
};
private static final FloatProperty<TaskView> FILL_DISMISS_GAP_TRANSLATION_X =
new FloatProperty<TaskView>("fillDismissGapTranslationX") {
private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
new FloatProperty<TaskView>("dismissTranslationX") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setFillDismissGapTranslationX(v);
taskView.setDismissTranslationX(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mFillDismissGapTranslationX;
return taskView.mDismissTranslationX;
}
};
private static final FloatProperty<TaskView> FILL_DISMISS_GAP_TRANSLATION_Y =
new FloatProperty<TaskView>("fillDismissGapTranslationY") {
private static final FloatProperty<TaskView> DISMISS_TRANSLATION_Y =
new FloatProperty<TaskView>("dismissTranslationY") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setFillDismissGapTranslationY(v);
taskView.setDismissTranslationY(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mFillDismissGapTranslationY;
return taskView.mDismissTranslationY;
}
};
@@ -204,6 +206,32 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
};
private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_X =
new FloatProperty<TaskView>("taskResistanceTranslationX") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setTaskResistanceTranslationX(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mTaskResistanceTranslationX;
}
};
private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_Y =
new FloatProperty<TaskView>("taskResistanceTranslationY") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setTaskResistanceTranslationY(v);
}
@Override
public Float get(TaskView taskView) {
return taskView.mTaskResistanceTranslationY;
}
};
private final OnAttachStateChangeListener mTaskMenuStateListener =
new OnAttachStateChangeListener() {
@Override
@@ -228,15 +256,22 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private final DigitalWellBeingToast mDigitalWellBeingToast;
private float mCurveScale;
private float mFullscreenProgress;
private float mScaleAtFullscreen = 1;
private float mFullscreenScale = 1;
private final FullscreenDrawParams mCurrentFullscreenParams;
private final StatefulActivity mActivity;
// Various causes of changing primary translation, which we aggregate to setTranslationX/Y().
// TODO: We should do this for secondary translation properties as well.
private float mFillDismissGapTranslationX;
private float mFillDismissGapTranslationY;
private float mDismissTranslationX;
private float mDismissTranslationY;
private float mTaskOffsetTranslationX;
private float mTaskOffsetTranslationY;
private float mTaskResistanceTranslationX;
private float mTaskResistanceTranslationY;
// The following translation variables should only be used in the same orientation as Launcher.
private float mFullscreenTranslationX;
private float mAccumulatedTranslationX;
private float mBoxTranslationY;
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
@@ -425,6 +460,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
cancelPendingLoadTasks();
mTask = task;
mSnapshotView.bind(task);
updateTaskSize();
setOrientationState(orientedState);
}
@@ -668,10 +704,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
protected void resetViewTransforms() {
setCurveScale(1);
mFillDismissGapTranslationX = mTaskOffsetTranslationX = 0f;
mFillDismissGapTranslationY = mTaskOffsetTranslationY = 0f;
setTranslationX(0f);
setTranslationY(0f);
// fullscreenTranslation and accumulatedTranslation should not be reset, as
// resetViewTransforms is called during Quickswitch scrolling.
mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX = 0f;
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
applyTranslationX();
applyTranslationY();
setTranslationZ(0);
setAlpha(mStableAlpha);
setIconScaleAndDim(1);
@@ -684,6 +722,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
@Override
public void onRecycle() {
mFullscreenTranslationX = mAccumulatedTranslationX = mBoxTranslationY = 0f;
resetViewTransforms();
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
@@ -702,7 +741,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
float curveInterpolation =
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
float curveScaleForCurveInterpolation = getCurveScaleForCurveInterpolation(
curveInterpolation);
mActivity.getDeviceProfile(), curveInterpolation);
mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
setCurveScale(curveScaleForCurveInterpolation);
@@ -787,40 +826,70 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
setPivotX((right - left) * 0.5f);
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? (right - left) : 0);
setPivotY(0);
} else {
setPivotX((right - left) * 0.5f);
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
}
if (Utilities.ATLEAST_Q) {
SYSTEM_GESTURE_EXCLUSION_RECT.get(0).set(0, 0, getWidth(), getHeight());
setSystemGestureExclusionRects(SYSTEM_GESTURE_EXCLUSION_RECT);
}
}
public static float getCurveScaleForInterpolation(float linearInterpolation) {
/**
* How much to scale down pages near the edge of the screen according to linearInterpolation.
*/
public static float getCurveScaleForInterpolation(DeviceProfile deviceProfile,
float linearInterpolation) {
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
return getCurveScaleForCurveInterpolation(curveInterpolation);
return getCurveScaleForCurveInterpolation(deviceProfile, curveInterpolation);
}
private static float getCurveScaleForCurveInterpolation(float curveInterpolation) {
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
private static float getCurveScaleForCurveInterpolation(DeviceProfile deviceProfile,
float curveInterpolation) {
return 1 - curveInterpolation * getEdgeScaleDownFactor(deviceProfile);
}
/**
* How much to scale down pages near the edge of the screen.
*/
public static float getEdgeScaleDownFactor(DeviceProfile deviceProfile) {
if (deviceProfile.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
return EDGE_SCALE_DOWN_FACTOR_GRID;
} else {
return EDGE_SCALE_DOWN_FACTOR_CAROUSEL;
}
}
private void setCurveScale(float curveScale) {
mCurveScale = curveScale;
setScaleX(mCurveScale);
setScaleY(mCurveScale);
applyScale();
}
private void setFullscreenScale(float fullscreenScale) {
mFullscreenScale = fullscreenScale;
applyScale();
}
private void applyScale() {
setScaleX(mCurveScale * mFullscreenScale);
setScaleY(mCurveScale * mFullscreenScale);
}
public float getCurveScale() {
return mCurveScale;
}
private void setFillDismissGapTranslationX(float x) {
mFillDismissGapTranslationX = x;
private void setDismissTranslationX(float x) {
mDismissTranslationX = x;
applyTranslationX();
}
private void setFillDismissGapTranslationY(float y) {
mFillDismissGapTranslationY = y;
private void setDismissTranslationY(float y) {
mDismissTranslationY = y;
applyTranslationY();
}
@@ -834,17 +903,59 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
applyTranslationY();
}
private void setTaskResistanceTranslationX(float x) {
mTaskResistanceTranslationX = x;
applyTranslationX();
}
private void setTaskResistanceTranslationY(float y) {
mTaskResistanceTranslationY = y;
applyTranslationY();
}
private void setFullscreenTranslationX(float fullscreenTranslationX) {
mFullscreenTranslationX = fullscreenTranslationX;
applyTranslationX();
}
public float getFullscreenTranslationX() {
return mFullscreenTranslationX;
}
public void setAccumulatedTranslationX(float accumulatedTranslationX) {
mAccumulatedTranslationX = accumulatedTranslationX;
applyTranslationX();
}
public float getAccumulatedTranslationX() {
return mAccumulatedTranslationX;
}
private void setBoxTranslationY(float boxTranslationY) {
mBoxTranslationY = boxTranslationY;
applyTranslationY();
}
private void applyTranslationX() {
setTranslationX(mFillDismissGapTranslationX + mTaskOffsetTranslationX);
setTranslationX(
mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
+ mFullscreenTranslationX + mAccumulatedTranslationX);
}
private void applyTranslationY() {
setTranslationY(mFillDismissGapTranslationY + mTaskOffsetTranslationY);
setTranslationY(
mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
+ mBoxTranslationY);
}
public FloatProperty<TaskView> getPrimaryFillDismissGapTranslationProperty() {
public FloatProperty<TaskView> getFillDismissGapTranslationProperty() {
return getPagedOrientationHandler().getPrimaryValue(
FILL_DISMISS_GAP_TRANSLATION_X, FILL_DISMISS_GAP_TRANSLATION_Y);
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
}
public FloatProperty<TaskView> getDismissTaskTranslationProperty() {
return getPagedOrientationHandler().getSecondaryValue(
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
}
public FloatProperty<TaskView> getPrimaryTaskOffsetTranslationProperty() {
@@ -852,6 +963,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
}
public FloatProperty<TaskView> getTaskResistanceTranslationProperty() {
return getPagedOrientationHandler().getSecondaryValue(
TASK_RESISTANCE_TRANSLATION_X, TASK_RESISTANCE_TRANSLATION_Y);
}
@Override
public boolean hasOverlappingRendering() {
// TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
@@ -987,6 +1103,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
setClipChildren(!isFullscreen);
setClipToPadding(!isFullscreen);
updateTaskScaling();
TaskThumbnailView thumbnail = getThumbnail();
updateCurrentFullscreenParams(thumbnail.getPreviewPositionHelper());
@@ -1012,6 +1130,83 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
previewPositionHelper);
}
void updateTaskSize() {
ViewGroup.LayoutParams params = getLayoutParams();
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
final int thumbnailPadding = (int) getResources().getDimension(
R.dimen.task_thumbnail_top_margin);
Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
int taskWidth = lastComputedTaskSize.width();
int taskHeight = lastComputedTaskSize.height();
int boxLength = Math.max(taskWidth, taskHeight);
float thumbnailRatio = mSnapshotView.getThumbnailRatio();
int expectedWidth;
int expectedHeight;
if (thumbnailRatio > 1) {
expectedWidth = boxLength;
expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding;
} else {
expectedWidth = (int) (boxLength * thumbnailRatio);
expectedHeight = boxLength + thumbnailPadding;
}
float heightDiff = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
setBoxTranslationY(heightDiff);
if (expectedWidth > taskWidth) {
// In full screen, expectedWidth should not be larger than taskWidth.
mScaleAtFullscreen = taskWidth / (float) expectedWidth;
} else if (expectedHeight - thumbnailPadding > taskHeight) {
// In full screen, expectedHeight should not be larger than taskHeight.
mScaleAtFullscreen = taskHeight / (float) (expectedHeight - thumbnailPadding);
} else {
mScaleAtFullscreen = 1f;
}
if (params.width != expectedWidth || params.height != expectedHeight) {
params.width = expectedWidth;
params.height = expectedHeight;
setLayoutParams(params);
}
} else {
setBoxTranslationY(0);
if (params.width != ViewGroup.LayoutParams.MATCH_PARENT) {
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
setLayoutParams(params);
}
}
updateTaskScaling();
}
private void updateTaskScaling() {
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
ViewGroup.LayoutParams params = getLayoutParams();
if (params.width == ViewGroup.LayoutParams.MATCH_PARENT
|| params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
// Snapshot is not loaded yet, skip.
return;
}
float progress = EXAGGERATED_EASE.getInterpolation(mFullscreenProgress);
setFullscreenScale(Utilities.mapRange(progress, 1f, mScaleAtFullscreen));
float widthDiff = params.width * (1 - mFullscreenScale);
setFullscreenTranslationX(getFullscreenTrans(
getLayoutDirection() == LAYOUT_DIRECTION_RTL ? -widthDiff : widthDiff));
} else {
setFullscreenScale(1);
setFullscreenTranslationX(0);
}
}
private float getFullscreenTrans(float endTranslation) {
float progress = ACCEL_DEACCEL.getInterpolation(mFullscreenProgress);
return Utilities.mapRange(progress, 0, endTranslation);
}
public boolean isRunningTask() {
if (getRecentsView() == null) {
return false;