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:
+5
-2
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user