Use snapshotView references in TaskContainer when possible

- Moved majority of TaskContainer.thumbnailViewDeprecated usage to TaskContainer.snapshotView, so they'll cover the new TaskThumbnailView as well
- There are afew location left that will be handled as a follow-up
- Removed TaskThumbnailView's splitTranslation and use translation directly as it's the only translation we use

Bug: 336612373
Test: Ensure all Task CUJs still work without refacorting
Test: Ensure major Task CUJs work with refactoring
Flag: EXEMPT refactor
Flag: com.android.launcher3.enable_refactor_task_thumbnail
Change-Id: Ieb52236bc503ce0d0a511249978c1821a82d406e
This commit is contained in:
Alex Chau
2024-05-30 12:28:07 +01:00
parent b76356a202
commit c06bc41ee0
13 changed files with 136 additions and 202 deletions
@@ -269,8 +269,8 @@ public class TaskbarUIController {
foundTaskView,
foundTask,
taskContainer.getIconView().getDrawable(),
taskContainer.getThumbnailViewDeprecated(),
taskContainer.getThumbnailViewDeprecated().getThumbnail(),
taskContainer.getSnapshotView(),
taskContainer.getThumbnail(),
null /* intent */,
null /* user */,
info);
@@ -252,7 +252,7 @@ public abstract class TaskViewTouchController<CONTAINER extends Context & Recent
mTaskBeingDragged, maxDuration, currentInterpolator);
// Since the thumbnail is what is filling the screen, based the end displacement on it.
View thumbnailView = mTaskBeingDragged.getFirstThumbnailViewDeprecated();
View thumbnailView = mTaskBeingDragged.getFirstSnapshotView();
mTempCords[1] = orientationHandler.getSecondaryDimension(thumbnailView);
dl.getDescendantCoordRelativeToSelf(thumbnailView, mTempCords);
mEndDisplacement = secondaryLayerDimension - mTempCords[1];
@@ -44,7 +44,6 @@ import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskContainer;
import com.android.systemui.shared.recents.model.Task;
@@ -134,20 +133,20 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
mApplicationContext = taskContainer.getTaskView().getContext().getApplicationContext();
mTaskContainer = taskContainer;
mImageApi = new ImageActionsApi(
mApplicationContext, mTaskContainer.getThumbnailViewDeprecated()::getThumbnail);
mApplicationContext, mTaskContainer::getThumbnail);
}
protected T getActionsView() {
if (mActionsView == null) {
mActionsView = BaseActivity.fromContext(
mTaskContainer.getThumbnailViewDeprecated().getContext()).findViewById(
mTaskContainer.getTaskView().getContext()).findViewById(
R.id.overview_actions_view);
}
return mActionsView;
}
public TaskThumbnailViewDeprecated getThumbnailView() {
return mTaskContainer.getThumbnailViewDeprecated();
public TaskView getTaskView() {
return mTaskContainer.getTaskView();
}
/**
@@ -159,8 +158,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
if (thumbnail != null) {
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
boolean isAllowedByPolicy =
mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot();
boolean isAllowedByPolicy = mTaskContainer.isRealSnapshot();
getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
}
}
@@ -172,7 +170,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
*/
public void endLiveTileMode(@NonNull Runnable callback) {
RecentsView recentsView =
mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
mTaskContainer.getTaskView().getRecentsView();
// Task has already been dismissed
if (recentsView == null) return;
recentsView.switchToScreenshot(
@@ -185,8 +183,8 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
*/
@SuppressLint("NewApi")
protected void saveScreenshot(Task task) {
if (mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()) {
mImageApi.saveScreenshot(mTaskContainer.getThumbnailViewDeprecated().getThumbnail(),
if (mTaskContainer.isRealSnapshot()) {
mImageApi.saveScreenshot(mTaskContainer.getThumbnail(),
getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key);
} else {
showBlockedByPolicyMessage();
@@ -194,17 +192,14 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
}
protected void enterSplitSelect() {
RecentsView overviewPanel =
mTaskContainer.getThumbnailViewDeprecated().getTaskView().getRecentsView();
RecentsView overviewPanel = mTaskContainer.getTaskView().getRecentsView();
// Task has already been dismissed
if (overviewPanel == null) return;
overviewPanel.initiateSplitSelect(
mTaskContainer.getThumbnailViewDeprecated().getTaskView());
overviewPanel.initiateSplitSelect(mTaskContainer.getTaskView());
}
protected void saveAppPair() {
GroupedTaskView taskView =
(GroupedTaskView) mTaskContainer.getThumbnailViewDeprecated().getTaskView();
GroupedTaskView taskView = (GroupedTaskView) mTaskContainer.getTaskView();
taskView.getRecentsView().getSplitSelectController().getAppPairsController()
.saveAppPair(taskView);
}
@@ -250,11 +245,11 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
*/
public Rect getTaskSnapshotBounds() {
int[] location = new int[2];
mTaskContainer.getThumbnailViewDeprecated().getLocationOnScreen(location);
mTaskContainer.getSnapshotView().getLocationOnScreen(location);
return new Rect(location[0], location[1],
mTaskContainer.getThumbnailViewDeprecated().getWidth() + location[0],
mTaskContainer.getThumbnailViewDeprecated().getHeight() + location[1]);
mTaskContainer.getSnapshotView().getWidth() + location[0],
mTaskContainer.getSnapshotView().getHeight() + location[1]);
}
/**
@@ -264,7 +259,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
*/
@RequiresApi(api = Build.VERSION_CODES.Q)
public Insets getTaskSnapshotInsets() {
return mTaskContainer.getThumbnailViewDeprecated().getScaledInsets();
return mTaskContainer.getScaledInsets();
}
/**
@@ -275,14 +270,14 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
protected void showBlockedByPolicyMessage() {
ActivityContext activityContext = ActivityContext.lookupContext(
mTaskContainer.getThumbnailViewDeprecated().getContext());
mTaskContainer.getTaskView().getContext());
String message = activityContext.getStringCache() != null
? activityContext.getStringCache().disabledByAdminMessage
: mTaskContainer.getThumbnailViewDeprecated().getContext().getString(
: mTaskContainer.getTaskView().getContext().getString(
R.string.blocked_by_policy);
Snackbar.show(BaseActivity.fromContext(
mTaskContainer.getThumbnailViewDeprecated().getContext()), message, null);
mTaskContainer.getTaskView().getContext()), message, null);
}
/** Called when the snapshot has updated its full screen drawing parameters. */
@@ -304,8 +299,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
@Override
public void onClick(View view) {
saveScreenshot(
mTaskContainer.getThumbnailViewDeprecated().getTaskView().getFirstTask());
saveScreenshot(mTaskContainer.getTaskView().getFirstTask());
dismissTaskMenuView();
}
}
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.view.Surface.ROTATION_0;
import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;
@@ -55,7 +56,6 @@ import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.TaskView.TaskContainer;
import com.android.systemui.shared.recents.model.Task;
@@ -174,7 +174,7 @@ public interface TaskShortcutFactory {
private Handler mHandler;
private final RecentsView mRecentsView;
private final TaskThumbnailViewDeprecated mThumbnailView;
private final TaskContainer mTaskContainer;
private final TaskView mTaskView;
private final LauncherEvent mLauncherEvent;
@@ -186,7 +186,7 @@ public interface TaskShortcutFactory {
mHandler = new Handler(Looper.getMainLooper());
mTaskView = taskContainer.getTaskView();
mRecentsView = container.getOverviewPanel();
mThumbnailView = taskContainer.getThumbnailViewDeprecated();
mTaskContainer = taskContainer;
}
@Override
@@ -220,20 +220,25 @@ public interface TaskShortcutFactory {
};
final int[] position = new int[2];
mThumbnailView.getLocationOnScreen(position);
final int width = (int) (mThumbnailView.getWidth() * mTaskView.getScaleX());
final int height = (int) (mThumbnailView.getHeight() * mTaskView.getScaleY());
View snapShotView = mTaskContainer.getSnapshotView();
snapShotView.getLocationOnScreen(position);
final int width = (int) (snapShotView.getWidth() * mTaskView.getScaleX());
final int height = (int) (snapShotView.getHeight() * mTaskView.getScaleY());
final Rect taskBounds = new Rect(position[0], position[1],
position[0] + width, position[1] + height);
// Take the thumbnail of the task without a scrim and apply it back after
float alpha = mThumbnailView.getDimAlpha();
// TODO(b/348643341) add ability to get override the scrim for this Bitmap retrieval
mThumbnailView.setDimAlpha(0);
float alpha = 0f;
if (!enableRefactorTaskThumbnail()) {
alpha = mTaskContainer.getThumbnailViewDeprecated().getDimAlpha();
mTaskContainer.getThumbnailViewDeprecated().setDimAlpha(0);
}
Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
taskBounds.width(), taskBounds.height(), mThumbnailView, 1f,
Color.BLACK);
mThumbnailView.setDimAlpha(alpha);
taskBounds.width(), taskBounds.height(), snapShotView, 1f, Color.BLACK);
if (!enableRefactorTaskThumbnail()) {
mTaskContainer.getThumbnailViewDeprecated().setDimAlpha(alpha);
}
AppTransitionAnimationSpecsFuture future =
new AppTransitionAnimationSpecsFuture(mHandler) {
@@ -80,7 +80,6 @@ import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.DesktopTaskView;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailViewDeprecated;
import com.android.quickstep.views.TaskView;
import com.android.systemui.animation.RemoteAnimationTargetCompat;
import com.android.systemui.shared.recents.model.Task;
@@ -334,7 +333,7 @@ public final class TaskViewUtils {
// During animation we apply transformation on the thumbnailView (and not the rootView)
// to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
// Mt K(0)` K(t) Mt`
TaskThumbnailViewDeprecated[] thumbnails = v.getThumbnailViews();
View[] thumbnails = v.getSnapshotViews();
// In case simulator copies and thumbnail size do no match, ensure we get the lesser.
// This ensures we do not create arrays with empty elements or attempt to references
@@ -344,7 +343,7 @@ public final class TaskViewUtils {
Matrix[] mt = new Matrix[matrixSize];
Matrix[] mti = new Matrix[matrixSize];
for (int i = 0; i < matrixSize; i++) {
TaskThumbnailViewDeprecated ttv = thumbnails[i];
View ttv = thumbnails[i];
RectF localBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
float[] tvBoundsMapped = new float[]{0, 0, ttv.getWidth(), ttv.getHeight()};
getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
@@ -391,7 +390,7 @@ public final class TaskViewUtils {
out.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
for (TaskThumbnailViewDeprecated ttv : thumbnails) {
for (View ttv : thumbnails) {
ttv.setAnimationMatrix(null);
}
}
@@ -43,6 +43,7 @@ import androidx.annotation.VisibleForTesting
import com.android.app.animation.Interpolators
import com.android.launcher3.DeviceProfile
import com.android.launcher3.Flags.enableOverviewIconMenu
import com.android.launcher3.Flags.enableRefactorTaskThumbnail
import com.android.launcher3.InsettableFrameLayout
import com.android.launcher3.QuickstepTransitionManager
import com.android.launcher3.R
@@ -118,8 +119,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
if (container.task.getKey().getId() == splitSelectStateController.initialTaskId) {
val drawable = getDrawable(container.iconView, splitSelectSource)
return SplitAnimInitProps(
container.thumbnailViewDeprecated,
container.thumbnailViewDeprecated.thumbnail,
container.snapshotView,
container.thumbnail,
drawable!!,
fadeWithThumbnail = true,
isStagedTask = true,
@@ -137,8 +138,8 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
taskView.taskContainers.first().let {
val drawable = getDrawable(it.iconView, splitSelectSource)
return SplitAnimInitProps(
it.thumbnailViewDeprecated,
it.thumbnailViewDeprecated.thumbnail,
it.snapshotView,
it.thumbnail,
drawable!!,
fadeWithThumbnail = true,
isStagedTask = true,
@@ -165,27 +166,37 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
/**
* When selecting first app from split pair, second app's thumbnail remains. This animates the
* second thumbnail by expanding it to take up the full taskViewWidth/Height and overlaying it
* with [TaskThumbnailViewDeprecated]'s splashView. Adds animations to the provided builder.
* Note: The app that **was not** selected as the first split app should be the container that's
* passed through.
* with [TaskContainer]'s splashView. Adds animations to the provided builder. Note: The app
* that **was not** selected as the first split app should be the container that's passed
* through.
*
* @param builder Adds animation to this
* @param taskIdAttributeContainer container of the app that **was not** selected
* @param taskContainer container of the app that **was not** selected
* @param isPrimaryTaskSplitting if true, task that was split would be top/left in the pair
* (opposite of that representing [taskIdAttributeContainer])
* (opposite of that representing [taskContainer])
*/
fun addInitialSplitFromPair(
taskIdAttributeContainer: TaskContainer,
taskContainer: TaskContainer,
builder: PendingAnimation,
deviceProfile: DeviceProfile,
taskViewWidth: Int,
taskViewHeight: Int,
isPrimaryTaskSplitting: Boolean
) {
val thumbnail = taskIdAttributeContainer.thumbnailViewDeprecated
val iconView: View = taskIdAttributeContainer.iconView.asView()
builder.add(ObjectAnimator.ofFloat(thumbnail, TaskThumbnailViewDeprecated.SPLASH_ALPHA, 1f))
thumbnail.setShowSplashForSplitSelection(true)
val snapshot = taskContainer.snapshotView
val iconView: View = taskContainer.iconView.asView()
// TODO(334826842): Switch to splash state in TaskThumbnailView
if (!enableRefactorTaskThumbnail()) {
val thumbnailViewDeprecated = taskContainer.thumbnailViewDeprecated
builder.add(
ObjectAnimator.ofFloat(
thumbnailViewDeprecated,
TaskThumbnailViewDeprecated.SPLASH_ALPHA,
1f
)
)
thumbnailViewDeprecated.setShowSplashForSplitSelection(true)
}
// With the new `IconAppChipView`, we always want to keep the chip pinned to the
// top left of the task / thumbnail.
if (enableOverviewIconMenu()) {
@@ -202,14 +213,10 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
}
if (deviceProfile.isLeftRightSplit) {
// Center view first so scaling happens uniformly, alternatively we can move pivotX to 0
val centerThumbnailTranslationX: Float = (taskViewWidth - thumbnail.width) / 2f
val finalScaleX: Float = taskViewWidth.toFloat() / thumbnail.width
val centerThumbnailTranslationX: Float = (taskViewWidth - snapshot.width) / 2f
val finalScaleX: Float = taskViewWidth.toFloat() / snapshot.width
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_X,
centerThumbnailTranslationX
)
ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_X, centerThumbnailTranslationX)
)
if (!enableOverviewIconMenu()) {
// icons are anchored from Gravity.END, so need to use negative translation
@@ -218,21 +225,15 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
ObjectAnimator.ofFloat(iconView, View.TRANSLATION_X, -centerIconTranslationX)
)
}
builder.add(ObjectAnimator.ofFloat(thumbnail, View.SCALE_X, finalScaleX))
builder.add(ObjectAnimator.ofFloat(snapshot, View.SCALE_X, finalScaleX))
// Reset other dimensions
// TODO(b/271468547), can't set Y translate to 0, need to account for top space
thumbnail.scaleY = 1f
snapshot.scaleY = 1f
val translateYResetVal: Float =
if (!isPrimaryTaskSplitting) 0f
else deviceProfile.overviewTaskThumbnailTopMarginPx.toFloat()
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_Y,
translateYResetVal
)
)
builder.add(ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_Y, translateYResetVal))
} else {
val thumbnailSize = taskViewHeight - deviceProfile.overviewTaskThumbnailTopMarginPx
// Center view first so scaling happens uniformly, alternatively we can move pivotY to 0
@@ -247,36 +248,26 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
// thumbnail needs to take that into account. We should migrate to only using
// translations otherwise this asymmetry causes problems..
if (isPrimaryTaskSplitting) {
centerThumbnailTranslationY = (thumbnailSize - thumbnail.height) / 2f
centerThumbnailTranslationY = (thumbnailSize - snapshot.height) / 2f
centerThumbnailTranslationY +=
deviceProfile.overviewTaskThumbnailTopMarginPx.toFloat()
} else {
centerThumbnailTranslationY = (thumbnailSize - thumbnail.height) / 2f
centerThumbnailTranslationY = (thumbnailSize - snapshot.height) / 2f
}
val finalScaleY: Float = thumbnailSize.toFloat() / thumbnail.height
val finalScaleY: Float = thumbnailSize.toFloat() / snapshot.height
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_Y,
centerThumbnailTranslationY
)
ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_Y, centerThumbnailTranslationY)
)
if (!enableOverviewIconMenu()) {
// icons are anchored from Gravity.END, so need to use negative translation
builder.add(ObjectAnimator.ofFloat(iconView, View.TRANSLATION_X, 0f))
}
builder.add(ObjectAnimator.ofFloat(thumbnail, View.SCALE_Y, finalScaleY))
builder.add(ObjectAnimator.ofFloat(snapshot, View.SCALE_Y, finalScaleY))
// Reset other dimensions
thumbnail.scaleX = 1f
builder.add(
ObjectAnimator.ofFloat(
thumbnail,
TaskThumbnailViewDeprecated.SPLIT_SELECT_TRANSLATE_X,
0f
)
)
snapshot.scaleX = 1f
builder.add(ObjectAnimator.ofFloat(snapshot, View.TRANSLATION_X, 0f))
}
}
@@ -128,7 +128,7 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
}
val thumbWidth = (taskSize.width() * scaleWidth).toInt()
val thumbHeight = (taskSize.height() * scaleHeight).toInt()
it.thumbnailViewDeprecated.measure(
it.snapshotView.measure(
MeasureSpec.makeMeasureSpec(thumbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(thumbHeight, MeasureSpec.EXACTLY)
)
@@ -139,8 +139,8 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
var taskY = (positionInParent.y * scaleHeight).toInt()
// move task down by margin size
taskY += thumbnailTopMarginPx
it.thumbnailViewDeprecated.x = taskX.toFloat()
it.thumbnailViewDeprecated.y = taskY.toFloat()
it.snapshotView.x = taskX.toFloat()
it.snapshotView.y = taskY.toFloat()
if (DEBUG) {
Log.d(
TAG,
@@ -332,12 +332,12 @@ public final class DigitalWellBeingToast {
(FrameLayout.LayoutParams) mBanner.getLayoutParams();
DeviceProfile deviceProfile = mContainer.getDeviceProfile();
layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams)
mTaskView.getFirstThumbnailViewDeprecated().getLayoutParams()).bottomMargin;
mTaskView.getFirstSnapshotView().getLayoutParams()).bottomMargin;
RecentsPagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler();
Pair<Float, Float> translations = orientationHandler
.getDwbLayoutTranslations(mTaskView.getMeasuredWidth(),
mTaskView.getMeasuredHeight(), mSplitBounds, deviceProfile,
mTaskView.getThumbnailViews(), mTask.key.id, mBanner);
mTaskView.getSnapshotViews(), mTask.key.id, mBanner);
mSplitOffsetTranslationX = translations.first;
mSplitOffsetTranslationY = translations.second;
updateTranslationY();
@@ -68,36 +68,20 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
if (initSplitTaskId == INVALID_TASK_ID) {
pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds(
taskContainers[0].thumbnailViewDeprecated,
taskContainers[1].thumbnailViewDeprecated,
taskContainers[0].snapshotView,
taskContainers[1].snapshotView,
widthSize,
heightSize,
splitBoundsConfig,
container.deviceProfile,
layoutDirection == LAYOUT_DIRECTION_RTL
)
// Should we be having a separate translation step apart from the measuring above?
// The following only applies to large screen for now, but for future reference
// we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
// translation directions
taskContainers[0]
.thumbnailViewDeprecated
.applySplitSelectTranslateX(taskContainers[0].thumbnailViewDeprecated.translationX)
taskContainers[0]
.thumbnailViewDeprecated
.applySplitSelectTranslateY(taskContainers[0].thumbnailViewDeprecated.translationY)
taskContainers[1]
.thumbnailViewDeprecated
.applySplitSelectTranslateX(taskContainers[1].thumbnailViewDeprecated.translationX)
taskContainers[1]
.thumbnailViewDeprecated
.applySplitSelectTranslateY(taskContainers[1].thumbnailViewDeprecated.translationY)
} else {
// Currently being split with this taskView, let the non-split selected thumbnail
// take up full thumbnail area
taskContainers
.firstOrNull { it.task.key.id != initSplitTaskId }
?.thumbnailViewDeprecated
?.snapshotView
?.measure(
widthMeasureSpec,
MeasureSpec.makeMeasureSpec(
@@ -212,8 +196,8 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
taskContainers[0].iconView.asView(),
taskContainers[1].iconView.asView(),
taskIconHeight,
taskContainers[0].thumbnailViewDeprecated.measuredWidth,
taskContainers[0].thumbnailViewDeprecated.measuredHeight,
taskContainers[0].snapshotView.measuredWidth,
taskContainers[0].snapshotView.measuredHeight,
measuredHeight,
measuredWidth,
isRtl,
@@ -308,7 +292,7 @@ class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
// Check which of the two apps was selected
if (
taskContainers[1].iconView.asView().containsPoint(lastTouchDownPosition) ||
taskContainers[1].thumbnailViewDeprecated.containsPoint(lastTouchDownPosition)
taskContainers[1].snapshotView.containsPoint(lastTouchDownPosition)
) {
return 1
}
@@ -238,12 +238,12 @@ public class TaskMenuView extends AbstractFloatingView {
mContainer.getDragLayer().getDescendantRectRelativeToSelf(
enableOverviewIconMenu()
? getIconView().findViewById(R.id.icon_view_menu_anchor)
: taskContainer.getThumbnailViewDeprecated(),
: taskContainer.getSnapshotView(),
sTempRect);
Rect insets = mContainer.getDragLayer().getInsets();
BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
params.width = orientationHandler.getTaskMenuWidth(
taskContainer.getThumbnailViewDeprecated(), deviceProfile,
taskContainer.getSnapshotView(), deviceProfile,
taskContainer.getStagePosition());
// Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
params.gravity = Gravity.LEFT;
@@ -277,10 +277,10 @@ public class TaskMenuView extends AbstractFloatingView {
// Margin that insets the menuView inside the taskView
float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin);
setTranslationX(orientationHandler.getTaskMenuX(thumbnailAlignedX,
mTaskContainer.getThumbnailViewDeprecated(), deviceProfile, taskInsetMargin,
mTaskContainer.getSnapshotView(), deviceProfile, taskInsetMargin,
getIconView()));
setTranslationY(orientationHandler.getTaskMenuY(
thumbnailAlignedY, mTaskContainer.getThumbnailViewDeprecated(),
thumbnailAlignedY, mTaskContainer.getSnapshotView(),
mTaskContainer.getStagePosition(), this, taskInsetMargin,
getIconView()));
}
@@ -316,7 +316,7 @@ public class TaskMenuView extends AbstractFloatingView {
.createRevealAnimator(this, closing, revealAnimationStartProgress);
mRevealAnimator.setInterpolator(enableOverviewIconMenu() ? Interpolators.EMPHASIZED
: Interpolators.DECELERATE);
AnimatorSet.Builder openCloseAnimatorBuilder = mOpenCloseAnimator.play(mRevealAnimator);
if (enableOverviewIconMenu()) {
IconAppChipView iconAppChip = (IconAppChipView) mTaskContainer.getIconView().asView();
@@ -334,11 +334,13 @@ public class TaskMenuView extends AbstractFloatingView {
closing ? mMenuTranslationYBeforeOpen
: mMenuTranslationYBeforeOpen + additionalTranslationY);
translationYAnim.setInterpolator(EMPHASIZED);
openCloseAnimatorBuilder.with(translationYAnim);
ObjectAnimator menuTranslationYAnim = ObjectAnimator.ofFloat(
iconAppChip.getMenuTranslationY(),
MULTI_PROPERTY_VALUE, closing ? 0 : additionalTranslationY);
menuTranslationYAnim.setInterpolator(EMPHASIZED);
openCloseAnimatorBuilder.with(menuTranslationYAnim);
float additionalTranslationX = 0;
if (mContainer.getDeviceProfile().isLandscape
@@ -354,20 +356,15 @@ public class TaskMenuView extends AbstractFloatingView {
closing ? mMenuTranslationXBeforeOpen
: mMenuTranslationXBeforeOpen - additionalTranslationX);
translationXAnim.setInterpolator(EMPHASIZED);
openCloseAnimatorBuilder.with(translationXAnim);
ObjectAnimator menuTranslationXAnim = ObjectAnimator.ofFloat(
iconAppChip.getMenuTranslationX(),
MULTI_PROPERTY_VALUE, closing ? 0 : -additionalTranslationX);
menuTranslationXAnim.setInterpolator(EMPHASIZED);
mOpenCloseAnimator.playTogether(translationYAnim, translationXAnim,
menuTranslationXAnim, menuTranslationYAnim);
openCloseAnimatorBuilder.with(menuTranslationXAnim);
}
mOpenCloseAnimator.playTogether(mRevealAnimator,
ObjectAnimator.ofFloat(
mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA,
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
openCloseAnimatorBuilder.with(ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
if (enableRefactorTaskThumbnail()) {
mRevealAnimator.addUpdateListener(animation -> {
float animatedFraction = animation.getAnimatedFraction();
@@ -375,6 +372,10 @@ public class TaskMenuView extends AbstractFloatingView {
mTaskContainer.getTaskContainerData()
.getTaskMenuOpenProgress().setValue(openProgress);
});
} else {
openCloseAnimatorBuilder.with(ObjectAnimator.ofFloat(
mTaskContainer.getThumbnailViewDeprecated(), DIM_ALPHA,
closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA));
}
mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
@Override
@@ -99,36 +99,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab
}
};
/** Use to animate thumbnail translationX while first app in split selection is initiated */
public static final Property<TaskThumbnailViewDeprecated, Float> SPLIT_SELECT_TRANSLATE_X =
new FloatProperty<TaskThumbnailViewDeprecated>("splitSelectTranslateX") {
@Override
public void setValue(TaskThumbnailViewDeprecated thumbnail,
float splitSelectTranslateX) {
thumbnail.applySplitSelectTranslateX(splitSelectTranslateX);
}
@Override
public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mSplitSelectTranslateX;
}
};
/** Use to animate thumbnail translationY while first app in split selection is initiated */
public static final Property<TaskThumbnailViewDeprecated, Float> SPLIT_SELECT_TRANSLATE_Y =
new FloatProperty<TaskThumbnailViewDeprecated>("splitSelectTranslateY") {
@Override
public void setValue(TaskThumbnailViewDeprecated thumbnail,
float splitSelectTranslateY) {
thumbnail.applySplitSelectTranslateY(splitSelectTranslateY);
}
@Override
public Float get(TaskThumbnailViewDeprecated thumbnailView) {
return thumbnailView.mSplitSelectTranslateY;
}
};
private final RecentsViewContainer mContainer;
private TaskOverlay<?> mOverlay;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -160,8 +130,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab
private boolean mOverlayEnabled;
/** Used as a placeholder when the original thumbnail animates out to. */
private boolean mShowSplashForSplitSelection;
private float mSplitSelectTranslateX;
private float mSplitSelectTranslateY;
public TaskThumbnailViewDeprecated(Context context) {
this(context, null);
@@ -415,31 +383,6 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab
}
}
/** See {@link #SPLIT_SELECT_TRANSLATE_X} */
protected void applySplitSelectTranslateX(float splitSelectTranslateX) {
mSplitSelectTranslateX = splitSelectTranslateX;
applyTranslateX();
}
/** See {@link #SPLIT_SELECT_TRANSLATE_Y} */
protected void applySplitSelectTranslateY(float splitSelectTranslateY) {
mSplitSelectTranslateY = splitSelectTranslateY;
applyTranslateY();
}
private void applyTranslateX() {
setTranslationX(mSplitSelectTranslateX);
}
private void applyTranslateY() {
setTranslationY(mSplitSelectTranslateY);
}
protected void resetViewTransforms() {
mSplitSelectTranslateX = 0;
mSplitSelectTranslateY = 0;
}
public TaskView getTaskView() {
return (TaskView) getParent();
}
@@ -23,7 +23,9 @@ import android.annotation.IdRes
import android.app.ActivityOptions
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Insets
import android.graphics.PointF
import android.graphics.Rect
import android.graphics.drawable.Drawable
@@ -138,8 +140,8 @@ constructor(
/** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
get() = taskContainers.map { it.task.key.id }.toIntArray()
val thumbnailViews: Array<TaskThumbnailViewDeprecated>
get() = taskContainers.map { it.thumbnailViewDeprecated }.toTypedArray()
val snapshotViews: Array<View>
get() = taskContainers.map { it.snapshotView }.toTypedArray()
val isGridTask: Boolean
/** Returns whether the task is part of overview grid and not being focused. */
@@ -170,6 +172,11 @@ constructor(
/** Returns the first thumbnailView of the TaskView. */
get() = taskContainers[0].thumbnailViewDeprecated
@get:Deprecated("Use [taskContainers] instead.")
val firstSnapshotView: View
/** Returns the first snapshotView of the TaskView. */
get() = taskContainers[0].snapshotView
@get:Deprecated("Use [taskContainers] instead.")
val firstItemInfo: ItemInfo
get() = taskContainers[0].itemInfo
@@ -1197,10 +1204,10 @@ constructor(
this,
container.task,
container.iconView.drawable,
container.thumbnailViewDeprecated,
container.thumbnailViewDeprecated.thumbnail, /* intent */
null, /* user */
null,
container.snapshotView,
container.thumbnail,
/* intent */ null,
/* user */ null,
container.itemInfo
)
}
@@ -1512,6 +1519,10 @@ constructor(
gridTranslationY = 0f
boxTranslationY = 0f
nonGridPivotTranslationX = 0f
taskContainers.forEach {
it.snapshotView.translationX = 0f
it.snapshotView.translationY = 0f
}
resetViewTransforms()
}
@@ -1537,10 +1548,6 @@ constructor(
alpha = stableAlpha
setIconScaleAndDim(1f)
setColorTint(0f, 0)
if (!enableRefactorTaskThumbnail()) {
// TODO(b/335399428) add split select functionality to new TTV
taskContainers.forEach { it.thumbnailViewDeprecated.resetViewTransforms() }
}
}
private fun getGridTrans(endTranslation: Float) =
@@ -1624,6 +1631,18 @@ constructor(
val snapshotView: View
get() = thumbnailView ?: thumbnailViewDeprecated
// TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel
val thumbnail: Bitmap?
get() = thumbnailViewDeprecated.thumbnail
// TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel
val isRealSnapshot: Boolean
get() = thumbnailViewDeprecated.isRealSnapshot()
// TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel
val scaledInsets: Insets
get() = thumbnailViewDeprecated.scaledInsets
/** Builds proto for logging */
val itemInfo: WorkspaceItemInfo
get() =
@@ -33,7 +33,6 @@ import com.android.launcher3.taskbar.TaskbarActivityContext
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.quickstep.views.GroupedTaskView
import com.android.quickstep.views.IconView
import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskContainer
import com.android.systemui.shared.recents.model.Task
@@ -59,7 +58,7 @@ class SplitAnimationControllerTest {
private val mockSplitSelectStateController: SplitSelectStateController = mock()
// TaskView
private val mockTaskView: TaskView = mock()
private val mockThumbnailView: TaskThumbnailViewDeprecated = mock()
private val mockSnapshotView: View = mock()
private val mockBitmap: Bitmap = mock()
private val mockIconView: IconView = mock()
private val mockTaskViewDrawable: Drawable = mock()
@@ -87,8 +86,8 @@ class SplitAnimationControllerTest {
@Before
fun setup() {
whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
whenever(mockThumbnailView.thumbnail).thenReturn(mockBitmap)
whenever(mockTaskContainer.snapshotView).thenReturn(mockSnapshotView)
whenever(mockTaskContainer.thumbnail).thenReturn(mockBitmap)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
whenever(mockIconView.drawable).thenReturn(mockTaskViewDrawable)
whenever(mockTaskView.taskContainers).thenReturn(List(1) { mockTaskContainer })
@@ -180,7 +179,6 @@ class SplitAnimationControllerTest {
whenever(mockTaskContainer.task).thenReturn(mockTask)
whenever(mockTaskContainer.iconView).thenReturn(mockIconView)
whenever(mockTaskContainer.thumbnailViewDeprecated).thenReturn(mockThumbnailView)
whenever(mockTask.getKey()).thenReturn(mockTaskKey)
whenever(mockTaskKey.getId()).thenReturn(taskId)
whenever(mockSplitSelectStateController.initialTaskId).thenReturn(taskId)