Snap for 7553152 from fda82bde99 to tm-release
Change-Id: I5b8e37f6b79daaf8a9b7ec13b6314f010d7d753b
This commit is contained in:
@@ -539,7 +539,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
@Override
|
||||
public void onMotionPauseDetected() {
|
||||
mHasMotionEverBeenPaused = true;
|
||||
maybeUpdateRecentsAttachedState();
|
||||
maybeUpdateRecentsAttachedState(true/* animate */, true/* moveFocusedTask */);
|
||||
performHapticFeedback();
|
||||
}
|
||||
|
||||
@@ -550,18 +550,24 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
};
|
||||
}
|
||||
|
||||
public void maybeUpdateRecentsAttachedState() {
|
||||
private void maybeUpdateRecentsAttachedState() {
|
||||
maybeUpdateRecentsAttachedState(true /* animate */);
|
||||
}
|
||||
|
||||
private void maybeUpdateRecentsAttachedState(boolean animate) {
|
||||
maybeUpdateRecentsAttachedState(animate, false /* moveFocusedTask */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether to show or hide RecentsView. The window is always
|
||||
* synchronized with its corresponding TaskView in RecentsView, so if
|
||||
* RecentsView is shown, it will appear to be attached to the window.
|
||||
*
|
||||
* Note this method has no effect unless the navigation mode is NO_BUTTON.
|
||||
* @param animate whether to animate when attaching RecentsView
|
||||
* @param moveFocusedTask whether to move focused task to front when attaching
|
||||
*/
|
||||
private void maybeUpdateRecentsAttachedState(boolean animate) {
|
||||
private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveFocusedTask) {
|
||||
if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
|
||||
return;
|
||||
}
|
||||
@@ -580,6 +586,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
} else {
|
||||
recentsAttachedToAppWindow = mHasMotionEverBeenPaused || mIsLikelyToStartNewTask;
|
||||
}
|
||||
if (moveFocusedTask && !mAnimationFactory.hasRecentsEverAttachedToAppWindow()
|
||||
&& recentsAttachedToAppWindow) {
|
||||
// Only move focused task if RecentsView has never been attached before, to avoid
|
||||
// TaskView jumping to new position as we move the tasks.
|
||||
mRecentsView.moveFocusedTaskToFront();
|
||||
}
|
||||
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
|
||||
|
||||
// Reapply window transform throughout the attach animation, as the animation affects how
|
||||
@@ -1025,9 +1037,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
if (mRecentsView != null) {
|
||||
int nearestPage = mRecentsView.getDestinationPage();
|
||||
boolean isScrolling = false;
|
||||
// Update page scroll before snapping to page to make sure we snapped to the
|
||||
// position calculated with target gesture in mind.
|
||||
mRecentsView.updateScrollSynchronously();
|
||||
if (mRecentsView.getNextPage() != nearestPage) {
|
||||
// We shouldn't really scroll to the next page when swiping up to recents.
|
||||
// Only allow settling on the next page if it's nearest to the center.
|
||||
@@ -1186,7 +1195,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mLauncherTransitionController = null;
|
||||
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget());
|
||||
mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget(),
|
||||
mTaskViewSimulator);
|
||||
}
|
||||
} else {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
@@ -1228,7 +1238,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
animatorSet.play(windowAnim);
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.onPrepareGestureEndAnimation(
|
||||
animatorSet, mGestureState.getEndTarget());
|
||||
animatorSet, mGestureState.getEndTarget(), mTaskViewSimulator);
|
||||
}
|
||||
animatorSet.setDuration(duration).setInterpolator(interpolator);
|
||||
animatorSet.start();
|
||||
|
||||
@@ -396,6 +396,10 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
default boolean isRecentsAttachedToAppWindow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean hasRecentsEverAttachedToAppWindow() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultAnimationFactory implements AnimationFactory {
|
||||
@@ -405,6 +409,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
private final Consumer<AnimatorControllerWithResistance> mCallback;
|
||||
|
||||
private boolean mIsAttachedToWindow;
|
||||
private boolean mHasEverAttachedToWindow;
|
||||
|
||||
DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
|
||||
mCallback = callback;
|
||||
@@ -458,6 +463,9 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
}
|
||||
mIsAttachedToWindow = attached;
|
||||
RecentsView recentsView = mActivity.getOverviewPanel();
|
||||
if (attached) {
|
||||
mHasEverAttachedToWindow = true;
|
||||
}
|
||||
Animator fadeAnim = mActivity.getStateManager()
|
||||
.createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
|
||||
|
||||
@@ -487,6 +495,11 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
return mIsAttachedToWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRecentsEverAttachedToAppWindow() {
|
||||
return mHasEverAttachedToWindow;
|
||||
}
|
||||
|
||||
protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
|
||||
// Scale down recents from being full screen to being in overview.
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.quickstep.FallbackActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.SplitPlaceholderView;
|
||||
@@ -89,8 +90,9 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
|
||||
*/
|
||||
@Override
|
||||
public void onPrepareGestureEndAnimation(
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
|
||||
super.onPrepareGestureEndAnimation(animatorSet, endTarget);
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget,
|
||||
TaskViewSimulator taskViewSimulator) {
|
||||
super.onPrepareGestureEndAnimation(animatorSet, endTarget, taskViewSimulator);
|
||||
if (mHomeTaskInfo != null && endTarget == RECENTS && animatorSet != null) {
|
||||
TaskView tv = getTaskView(mHomeTaskInfo.taskId);
|
||||
if (tv != null) {
|
||||
|
||||
@@ -1111,6 +1111,35 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the focused task to the front of the carousel in tablets, to minimize animation
|
||||
* required to focus the task in grid.
|
||||
*/
|
||||
public void moveFocusedTaskToFront() {
|
||||
if (!(mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get())) {
|
||||
return;
|
||||
}
|
||||
|
||||
TaskView focusedTaskView = getFocusedTaskView();
|
||||
if (focusedTaskView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexOfChild(focusedTaskView) != mCurrentPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
|
||||
int currentPageScroll = getScrollForPage(mCurrentPage);
|
||||
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
|
||||
|
||||
removeView(focusedTaskView);
|
||||
addView(focusedTaskView, mTaskViewStartIndex);
|
||||
setCurrentPage(0);
|
||||
|
||||
updateGridProperties();
|
||||
}
|
||||
|
||||
protected void applyLoadPlan(ArrayList<Task> tasks) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.addEndListener(success -> applyLoadPlan(tasks));
|
||||
@@ -1769,24 +1798,33 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
* Called when a gesture from an app has finished, and an end target has been determined.
|
||||
*/
|
||||
public void onPrepareGestureEndAnimation(
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget,
|
||||
TaskViewSimulator taskViewSimulator) {
|
||||
mCurrentGestureEndTarget = endTarget;
|
||||
if (endTarget == GestureState.GestureEndTarget.RECENTS) {
|
||||
setEnableFreeScroll(true);
|
||||
updateGridProperties();
|
||||
}
|
||||
|
||||
if (mSizeStrategy.stateFromGestureEndTarget(endTarget)
|
||||
.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
|
||||
TaskView runningTaskView = getRunningTaskView();
|
||||
float runningTaskPrimaryGridTranslation = 0;
|
||||
if (indexOfChild(runningTaskView) != getNextPage()) {
|
||||
// Apply the gird translation to running task unless it's being snapped to.
|
||||
runningTaskPrimaryGridTranslation = mOrientationHandler.getPrimaryValue(
|
||||
runningTaskView.getGridTranslationX(),
|
||||
runningTaskView.getGridTranslationY());
|
||||
}
|
||||
if (animatorSet == null) {
|
||||
setGridProgress(1);
|
||||
taskViewSimulator.taskPrimaryTranslation.value = runningTaskPrimaryGridTranslation;
|
||||
} else {
|
||||
animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1));
|
||||
animatorSet.play(taskViewSimulator.taskPrimaryTranslation.animateToValue(
|
||||
runningTaskPrimaryGridTranslation));
|
||||
}
|
||||
}
|
||||
mCurrentGestureEndTarget = endTarget;
|
||||
if (endTarget == GestureState.GestureEndTarget.NEW_TASK
|
||||
|| endTarget == GestureState.GestureEndTarget.LAST_TASK) {
|
||||
// When switching to tasks in quick switch, ensures the snapped page's scroll maintain
|
||||
// invariant between quick switch and overview, to ensure a smooth animation transition.
|
||||
updateGridProperties();
|
||||
} else if (endTarget == GestureState.GestureEndTarget.RECENTS) {
|
||||
setEnableFreeScroll(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2073,12 +2111,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
|
||||
}
|
||||
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
TaskView taskView = getTaskViewAt(i);
|
||||
taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX
|
||||
+ snappedTaskNonGridScrollAdjustment);
|
||||
}
|
||||
|
||||
// Use the accumulated translation of the row containing the last task.
|
||||
float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1)
|
||||
? topAccumulatedTranslationX : bottomAccumulatedTranslationX;
|
||||
@@ -2121,17 +2153,23 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// Make sure there are enough space between snapped page and ClearAllButton, for the case
|
||||
// of swiping up after quick switch.
|
||||
if (snappedTaskView != null) {
|
||||
int distanceFromClearAll = longRowWidth - snappedTaskRowWidth;
|
||||
int distanceFromClearAll = longRowWidth - snappedTaskRowWidth + mPageSpacing;
|
||||
// ClearAllButton should be off screen when snapped task is in its snapped position.
|
||||
int minimumDistance =
|
||||
mTaskWidth - snappedTaskView.getLayoutParams().width
|
||||
+ (mLastComputedGridSize.width() - mTaskWidth) / 2;
|
||||
if (distanceFromClearAll < minimumDistance) {
|
||||
int distanceDifference = minimumDistance - distanceFromClearAll;
|
||||
clearAllTotalTranslationX += mIsRtl ? -distanceDifference : distanceDifference;
|
||||
snappedTaskGridTranslationX += mIsRtl ? distanceDifference : -distanceDifference;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
TaskView taskView = getTaskViewAt(i);
|
||||
taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX
|
||||
+ snappedTaskNonGridScrollAdjustment);
|
||||
}
|
||||
|
||||
mClearAllButton.setGridTranslationPrimary(
|
||||
clearAllTotalTranslationX - snappedTaskGridTranslationX);
|
||||
mClearAllButton.setGridScrollOffset(
|
||||
@@ -2495,12 +2533,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
resetTaskVisuals();
|
||||
|
||||
int pageToSnapTo = mCurrentPage;
|
||||
if (finalNextFocusedTaskView != null) {
|
||||
pageToSnapTo = indexOfChild(finalNextFocusedTaskView);
|
||||
}
|
||||
if (dismissedIndex < pageToSnapTo || pageToSnapTo == (taskCount - 1)) {
|
||||
if ((dismissedIndex < pageToSnapTo && !showAsGrid)
|
||||
|| pageToSnapTo == taskCount - 1) {
|
||||
pageToSnapTo -= 1;
|
||||
}
|
||||
if (showAsGrid) {
|
||||
int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
|
||||
int currentPageScroll = getScrollForPage(pageToSnapTo);
|
||||
mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
|
||||
}
|
||||
removeViewInLayout(dismissedTaskView);
|
||||
mTopRowIdSet.remove(dismissedTaskId);
|
||||
|
||||
@@ -2513,12 +2554,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mFocusedTaskId = finalNextFocusedTaskView.getTaskId();
|
||||
mTopRowIdSet.remove(mFocusedTaskId);
|
||||
finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
|
||||
setCurrentPage(pageToSnapTo);
|
||||
}
|
||||
updateTaskSize(true);
|
||||
// Update scroll and snap to page.
|
||||
updateScrollSynchronously();
|
||||
snapToPageImmediately(pageToSnapTo);
|
||||
setCurrentPage(pageToSnapTo);
|
||||
dispatchScrollChanged();
|
||||
}
|
||||
}
|
||||
@@ -2860,6 +2900,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mLastComputedTaskStartPushOutDistance = null;
|
||||
mLastComputedTaskEndPushOutDistance = null;
|
||||
updatePageOffsets();
|
||||
mLiveTileTaskViewSimulator.setScroll(getScrollOffset());
|
||||
setImportantForAccessibility(isModal() ? IMPORTANT_FOR_ACCESSIBILITY_NO
|
||||
: IMPORTANT_FOR_ACCESSIBILITY_AUTO);
|
||||
}
|
||||
@@ -3622,18 +3663,28 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
boolean pageScrollChanged = false;
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
float scrollDiff = 0;
|
||||
if (child instanceof TaskView) {
|
||||
scrollDiff = ((TaskView) child).getScrollAdjustment(showAsFullscreen, showAsGrid);
|
||||
} else if (child instanceof ClearAllButton) {
|
||||
scrollDiff = ((ClearAllButton) child).getScrollAdjustment(showAsFullscreen,
|
||||
showAsGrid);
|
||||
}
|
||||
|
||||
final int pageScroll = newPageScrolls[i] + (int) scrollDiff;
|
||||
int clearAllIndex = indexOfChild(mClearAllButton);
|
||||
int clearAllScroll = 0;
|
||||
int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
|
||||
if (clearAllIndex != -1 && clearAllIndex < outPageScrolls.length) {
|
||||
float scrollDiff = mClearAllButton.getScrollAdjustment(showAsFullscreen, showAsGrid);
|
||||
clearAllScroll = newPageScrolls[clearAllIndex] + (int) scrollDiff;
|
||||
if (outPageScrolls[clearAllIndex] != clearAllScroll) {
|
||||
pageScrollChanged = true;
|
||||
outPageScrolls[clearAllIndex] = clearAllScroll;
|
||||
}
|
||||
}
|
||||
|
||||
final int taskCount = getTaskViewCount();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
TaskView taskView = getTaskViewAt(i);
|
||||
float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
|
||||
int pageScroll = newPageScrolls[i + mTaskViewStartIndex] + (int) scrollDiff;
|
||||
if ((mIsRtl && pageScroll < clearAllScroll)
|
||||
|| (!mIsRtl && pageScroll > clearAllScroll)) {
|
||||
pageScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
|
||||
}
|
||||
if (outPageScrolls[i] != pageScroll) {
|
||||
pageScrollChanged = true;
|
||||
outPageScrolls[i] = pageScroll;
|
||||
|
||||
@@ -794,7 +794,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
mIconView.setRotation(orientationHandler.getDegreesRotated());
|
||||
snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
|
||||
mSnapshotView.setLayoutParams(snapshotParams);
|
||||
getThumbnail().getTaskOverlay().updateOrientationState(orientationState);
|
||||
mSnapshotView.getTaskOverlay().updateOrientationState(orientationState);
|
||||
}
|
||||
|
||||
private void setIconAndDimTransitionProgress(float progress, boolean invert) {
|
||||
@@ -958,6 +958,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
|
||||
private void setNonGridScale(float nonGridScale) {
|
||||
mNonGridScale = nonGridScale;
|
||||
updateCornerRadius();
|
||||
applyScale();
|
||||
}
|
||||
|
||||
@@ -1296,18 +1297,21 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
progress = Utilities.boundToRange(progress, 0, 1);
|
||||
mFullscreenProgress = progress;
|
||||
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
|
||||
getThumbnail().getTaskOverlay().setFullscreenProgress(progress);
|
||||
mSnapshotView.getTaskOverlay().setFullscreenProgress(progress);
|
||||
|
||||
TaskThumbnailView thumbnail = getThumbnail();
|
||||
updateCurrentFullscreenParams(thumbnail.getPreviewPositionHelper());
|
||||
updateCornerRadius();
|
||||
|
||||
thumbnail.setFullscreenParams(mCurrentFullscreenParams);
|
||||
mSnapshotView.setFullscreenParams(mCurrentFullscreenParams);
|
||||
mOutlineProvider.updateParams(
|
||||
mCurrentFullscreenParams,
|
||||
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx);
|
||||
invalidateOutline();
|
||||
}
|
||||
|
||||
private void updateCornerRadius() {
|
||||
updateCurrentFullscreenParams(mSnapshotView.getPreviewPositionHelper());
|
||||
}
|
||||
|
||||
void updateCurrentFullscreenParams(PreviewPositionHelper previewPositionHelper) {
|
||||
if (getRecentsView() == null) {
|
||||
return;
|
||||
@@ -1315,7 +1319,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
mCurrentFullscreenParams.setProgress(
|
||||
mFullscreenProgress,
|
||||
getRecentsView().getScaleX(),
|
||||
getScaleX(),
|
||||
mNonGridScale,
|
||||
getWidth(), mActivity.getDeviceProfile(),
|
||||
previewPositionHelper);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,10 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
protected int mCurrentPage;
|
||||
// Difference between current scroll position and mCurrentPage's page scroll. Used to maintain
|
||||
// relative scroll position unchanged in updateCurrentPageScroll. Cleared when snapping to a
|
||||
// page.
|
||||
protected int mCurrentPageScrollDiff;
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
protected int mNextPage = INVALID_PAGE;
|
||||
@@ -247,7 +251,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
// If the current page is invalid, just reset the scroll position to zero
|
||||
int newPosition = 0;
|
||||
if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
|
||||
newPosition = getScrollForPage(mCurrentPage);
|
||||
newPosition = getScrollForPage(mCurrentPage) + mCurrentPageScrollDiff;
|
||||
}
|
||||
mOrientationHandler.set(this, VIEW_SCROLL_TO, newPosition);
|
||||
mScroller.startScroll(mScroller.getCurrX(), 0, newPosition - mScroller.getCurrX(), 0);
|
||||
@@ -452,6 +456,7 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
* to provide custom behavior during animation.
|
||||
*/
|
||||
protected void onPageEndTransition() {
|
||||
mCurrentPageScrollDiff = 0;
|
||||
AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
|
||||
AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
|
||||
AccessibilityEvent.TYPE_VIEW_FOCUSED, null);
|
||||
|
||||
@@ -477,10 +477,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
} else {
|
||||
mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
|
||||
mAH[AdapterHolder.WORK].recyclerView = null;
|
||||
if (mWorkModeSwitch != null) {
|
||||
((ViewGroup) mWorkModeSwitch.getParent()).removeView(mWorkModeSwitch);
|
||||
mWorkModeSwitch = null;
|
||||
}
|
||||
}
|
||||
setupHeader();
|
||||
|
||||
@@ -532,7 +528,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
|
||||
@Override
|
||||
public void onActivePageChanged(int currentActivePage) {
|
||||
mHeader.setMainActive(currentActivePage == 0);
|
||||
mHeader.setMainActive(currentActivePage == AdapterHolder.MAIN);
|
||||
if (mAH[currentActivePage].recyclerView != null) {
|
||||
mAH[currentActivePage].recyclerView.bindFastScrollbar();
|
||||
}
|
||||
@@ -541,6 +537,14 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
mWorkModeSwitch.setWorkTabVisible(currentActivePage == AdapterHolder.WORK
|
||||
&& mAllAppsStore.hasModelFlag(
|
||||
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
|
||||
|
||||
if (currentActivePage == AdapterHolder.WORK) {
|
||||
if (mWorkModeSwitch.getParent() == null) {
|
||||
addView(mWorkModeSwitch);
|
||||
}
|
||||
} else {
|
||||
removeView(mWorkModeSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,12 @@ public abstract class DragView<T extends Context & ActivityContext> extends Fram
|
||||
|
||||
addView(content, new LayoutParams(width, height));
|
||||
|
||||
// If there is already a scale set on the content, we don't want to clip the children.
|
||||
if (content.getScaleX() != 1 || content.getScaleY() != 1) {
|
||||
setClipChildren(false);
|
||||
setClipToPadding(false);
|
||||
}
|
||||
|
||||
final float scale = (width + finalScaleDps) / width;
|
||||
|
||||
// Set the initial scale to avoid any jumps
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
|
||||
import static com.android.launcher3.Utilities.ATLEAST_S;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.CancellationSignal;
|
||||
import android.util.AttributeSet;
|
||||
@@ -31,6 +33,7 @@ import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnLayoutChangeListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -43,6 +46,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.CheckLongPressHelper;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.RoundDrawableWrapper;
|
||||
@@ -71,11 +75,36 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
/** Widget preview width is calculated by multiplying this factor to the widget cell width. */
|
||||
private static final float PREVIEW_SCALE = 0.8f;
|
||||
|
||||
protected int mPreviewWidth;
|
||||
protected int mPreviewHeight;
|
||||
/**
|
||||
* The maximum dimension that can be used as the size in
|
||||
* {@link android.view.View.MeasureSpec#makeMeasureSpec(int, int)}.
|
||||
*
|
||||
* <p>This is equal to (1 << MeasureSpec.MODE_SHIFT) - 1.
|
||||
*/
|
||||
private static final int MAX_MEASURE_SPEC_DIMENSION = (1 << 30) - 1;
|
||||
|
||||
/**
|
||||
* The target preview width, in pixels, of a widget or a shortcut.
|
||||
*
|
||||
* <p>The actual preview width may be smaller than or equal to this value subjected to scaling.
|
||||
*/
|
||||
protected int mTargetPreviewWidth;
|
||||
|
||||
/**
|
||||
* The target preview height, in pixels, of a widget or a shortcut.
|
||||
*
|
||||
* <p>The actual preview height may be smaller than or equal to this value subjected to scaling.
|
||||
*/
|
||||
protected int mTargetPreviewHeight;
|
||||
|
||||
protected int mPresetPreviewSize;
|
||||
|
||||
private int mCellSize;
|
||||
private float mPreviewScale = 1f;
|
||||
|
||||
/**
|
||||
* The scale of the preview container.
|
||||
*/
|
||||
private float mPreviewContainerScale = 1f;
|
||||
|
||||
private FrameLayout mWidgetImageContainer;
|
||||
private WidgetImageView mWidgetImage;
|
||||
@@ -96,7 +125,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
protected final BaseActivity mActivity;
|
||||
private final CheckLongPressHelper mLongPressHelper;
|
||||
private final float mEnforcedCornerRadius;
|
||||
private final int mShortcutPreviewPadding;
|
||||
|
||||
private RemoteViews mRemoteViewsPreview;
|
||||
private NavigableAppWidgetHostView mAppWidgetHostViewPreview;
|
||||
@@ -122,14 +150,12 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
setClipToPadding(false);
|
||||
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
|
||||
mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
|
||||
mShortcutPreviewPadding =
|
||||
2 * getResources().getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
|
||||
}
|
||||
|
||||
private void setContainerWidth() {
|
||||
mCellSize = (int) (mActivity.getDeviceProfile().allAppsIconSizePx * WIDTH_SCALE);
|
||||
mPresetPreviewSize = (int) (mCellSize * PREVIEW_SCALE);
|
||||
mPreviewWidth = mPreviewHeight = mPresetPreviewSize;
|
||||
mTargetPreviewWidth = mTargetPreviewHeight = mPresetPreviewSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,7 +192,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
mWidgetDims.setText(null);
|
||||
mWidgetDescription.setText(null);
|
||||
mWidgetDescription.setVisibility(GONE);
|
||||
mPreviewWidth = mPreviewHeight = mPresetPreviewSize;
|
||||
mTargetPreviewWidth = mTargetPreviewHeight = mPresetPreviewSize;
|
||||
|
||||
if (mActiveRequest != null) {
|
||||
mActiveRequest.cancel();
|
||||
@@ -217,12 +243,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
|
||||
private void applyPreviewOnAppWidgetHostView(WidgetItem item) {
|
||||
if (mRemoteViewsPreview != null) {
|
||||
mAppWidgetHostViewPreview = new NavigableAppWidgetHostView(getContext()) {
|
||||
@Override
|
||||
protected boolean shouldAllowDirectClick() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
mAppWidgetHostViewPreview = createAppWidgetHostView(getContext());
|
||||
setAppWidgetHostViewPreview(mAppWidgetHostViewPreview, item.widgetInfo,
|
||||
mRemoteViewsPreview);
|
||||
return;
|
||||
@@ -230,10 +251,15 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
|
||||
if (!item.hasPreviewLayout()) return;
|
||||
|
||||
mAppWidgetHostViewPreview = new LauncherAppWidgetHostView(getContext());
|
||||
Context context = getContext();
|
||||
// If the context is a Launcher activity, DragView will show mAppWidgetHostViewPreview as
|
||||
// a preview during drag & drop. And thus, we should use LauncherAppWidgetHostView, which
|
||||
// supports applying local color extraction during drag & drop.
|
||||
mAppWidgetHostViewPreview = isLauncherContext(context)
|
||||
? new LauncherAppWidgetHostView(context)
|
||||
: createAppWidgetHostView(context);
|
||||
LauncherAppWidgetProviderInfo launcherAppWidgetProviderInfo =
|
||||
LauncherAppWidgetProviderInfo.fromProviderInfo(getContext(),
|
||||
item.widgetInfo.clone());
|
||||
LauncherAppWidgetProviderInfo.fromProviderInfo(context, item.widgetInfo.clone());
|
||||
// A hack to force the initial layout to be the preview layout since there is no API for
|
||||
// rendering a preview layout for work profile apps yet. For non-work profile layout, a
|
||||
// proper solution is to use RemoteViews(PackageName, LayoutId).
|
||||
@@ -248,16 +274,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
@Nullable RemoteViews remoteViews) {
|
||||
appWidgetHostViewPreview.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
appWidgetHostViewPreview.setAppWidget(/* appWidgetId= */ -1, providerInfo);
|
||||
Rect padding;
|
||||
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
|
||||
if (deviceProfile.shouldInsetWidgets()) {
|
||||
padding = new Rect();
|
||||
appWidgetHostViewPreview.getWidgetInset(deviceProfile, padding);
|
||||
} else {
|
||||
padding = deviceProfile.inv.defaultWidgetPadding;
|
||||
}
|
||||
appWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right,
|
||||
padding.bottom);
|
||||
appWidgetHostViewPreview.updateAppWidget(remoteViews);
|
||||
}
|
||||
|
||||
@@ -305,7 +321,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
if (getWidth() > 0 && getHeight() > 0) {
|
||||
// Scale down the preview size if it's wider than the cell.
|
||||
float maxWidth = getWidth();
|
||||
float previewWidth = drawable.getIntrinsicWidth() * mPreviewScale;
|
||||
float previewWidth = drawable.getIntrinsicWidth() * mPreviewContainerScale;
|
||||
scale = Math.min(maxWidth / previewWidth, 1);
|
||||
}
|
||||
setContainerSize(
|
||||
@@ -329,16 +345,32 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
|
||||
private void setContainerSize(int width, int height) {
|
||||
LayoutParams layoutParams = (LayoutParams) mWidgetImageContainer.getLayoutParams();
|
||||
layoutParams.width = (int) (width * mPreviewScale);
|
||||
layoutParams.height = (int) (height * mPreviewScale);
|
||||
layoutParams.width = width;
|
||||
layoutParams.height = height;
|
||||
mWidgetImageContainer.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
public void ensurePreview() {
|
||||
if (mAppWidgetHostViewPreview != null) {
|
||||
setContainerSize(mPreviewWidth, mPreviewHeight);
|
||||
int containerWidth = (int) (mTargetPreviewWidth * mPreviewContainerScale);
|
||||
int containerHeight = (int) (mTargetPreviewHeight * mPreviewContainerScale);
|
||||
setContainerSize(containerWidth, containerHeight);
|
||||
if (mAppWidgetHostViewPreview.getChildCount() == 1) {
|
||||
View widgetContent = mAppWidgetHostViewPreview.getChildAt(0);
|
||||
ViewGroup.LayoutParams layoutParams = widgetContent.getLayoutParams();
|
||||
// We only scale preview if both the width & height of the outermost view group are
|
||||
// not set to MATCH_PARENT.
|
||||
boolean shouldScale =
|
||||
layoutParams.width != MATCH_PARENT && layoutParams.height != MATCH_PARENT;
|
||||
if (shouldScale) {
|
||||
setNoClip(mWidgetImageContainer);
|
||||
setNoClip(mAppWidgetHostViewPreview);
|
||||
float previewLayoutScale = computeWidgetPreviewScale();
|
||||
mAppWidgetHostViewPreview.setScaleToFit(previewLayoutScale);
|
||||
}
|
||||
}
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||
mPreviewWidth, mPreviewHeight, Gravity.FILL);
|
||||
containerWidth, containerHeight, Gravity.FILL);
|
||||
mAppWidgetHostViewPreview.setLayoutParams(params);
|
||||
mWidgetImageContainer.addView(mAppWidgetHostViewPreview, /* index= */ 0);
|
||||
mWidgetImage.setVisibility(View.GONE);
|
||||
@@ -350,7 +382,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
}
|
||||
mActiveRequest = mWidgetPreviewLoader.loadPreview(
|
||||
BaseActivity.fromContext(getContext()), mItem,
|
||||
new Size(mPreviewWidth, mPreviewHeight),
|
||||
new Size(mTargetPreviewWidth, mTargetPreviewHeight),
|
||||
this::applyPreview);
|
||||
}
|
||||
|
||||
@@ -363,9 +395,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
public Size setPreviewSize(WidgetItem widgetItem, float previewScale) {
|
||||
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
|
||||
Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, widgetItem);
|
||||
mPreviewWidth = widgetSize.getWidth();
|
||||
mPreviewHeight = widgetSize.getHeight();
|
||||
mPreviewScale = previewScale;
|
||||
mTargetPreviewWidth = widgetSize.getWidth();
|
||||
mTargetPreviewHeight = widgetSize.getHeight();
|
||||
mPreviewContainerScale = previewScale;
|
||||
return widgetSize;
|
||||
}
|
||||
|
||||
@@ -400,6 +432,24 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
return "";
|
||||
}
|
||||
|
||||
private static NavigableAppWidgetHostView createAppWidgetHostView(Context context) {
|
||||
return new NavigableAppWidgetHostView(context) {
|
||||
@Override
|
||||
protected boolean shouldAllowDirectClick() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isLauncherContext(Context context) {
|
||||
try {
|
||||
Launcher.getLauncher(context);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAccessibilityClassName() {
|
||||
return WidgetCell.class.getName();
|
||||
@@ -410,4 +460,35 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
|
||||
}
|
||||
|
||||
private static void setNoClip(ViewGroup view) {
|
||||
view.setClipChildren(false);
|
||||
view.setClipToPadding(false);
|
||||
}
|
||||
|
||||
private float computeWidgetPreviewScale() {
|
||||
if (mAppWidgetHostViewPreview.getChildCount() != 1) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
// Measure the largest possible width & height that the app widget wants to display.
|
||||
mAppWidgetHostViewPreview.measure(
|
||||
makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED),
|
||||
makeMeasureSpec(MAX_MEASURE_SPEC_DIMENSION, MeasureSpec.UNSPECIFIED));
|
||||
int appWidgetContentWidth = mAppWidgetHostViewPreview.getChildAt(0).getMeasuredWidth();
|
||||
int appWidgetContentHeight = mAppWidgetHostViewPreview.getChildAt(0).getMeasuredHeight();
|
||||
if (appWidgetContentWidth == 0 || appWidgetContentHeight == 0) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
int horizontalPadding = mAppWidgetHostViewPreview.getPaddingStart()
|
||||
+ mAppWidgetHostViewPreview.getPaddingEnd();
|
||||
int verticalPadding = mAppWidgetHostViewPreview.getPaddingTop()
|
||||
+ mAppWidgetHostViewPreview.getPaddingBottom();
|
||||
return Math.min(
|
||||
(mTargetPreviewWidth - horizontalPadding) * mPreviewContainerScale
|
||||
/ appWidgetContentWidth,
|
||||
(mTargetPreviewHeight - verticalPadding) * mPreviewContainerScale
|
||||
/ appWidgetContentHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
.collect(Collectors.toList()),
|
||||
mLauncher.getVisibleBounds(searchBox).bottom
|
||||
- mLauncher.getVisibleBounds(allAppsContainer).top);
|
||||
verifyActiveContainer();
|
||||
final int newScroll = getAllAppsScroll();
|
||||
mLauncher.assertTrue(
|
||||
"Scrolled in a wrong direction in AllApps: from " + scroll + " to "
|
||||
@@ -144,7 +145,6 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
mLauncher.assertTrue(
|
||||
"Exceeded max scroll attempts: " + MAX_SCROLL_ATTEMPTS,
|
||||
++attempts <= MAX_SCROLL_ATTEMPTS);
|
||||
verifyActiveContainer();
|
||||
scroll = newScroll;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ public final class LauncherInstrumentation {
|
||||
checkForAnomaly();
|
||||
Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
|
||||
"http://go/tapl test failure:\nContext: " + getContextDescription()
|
||||
+ " - visible state is " + getVisibleStateMessage()
|
||||
+ " => resulting visible state is " + getVisibleStateMessage()
|
||||
+ ";\nDetails: " + message, true)));
|
||||
}
|
||||
|
||||
@@ -699,7 +699,8 @@ public final class LauncherInstrumentation {
|
||||
* @return the Workspace object.
|
||||
*/
|
||||
public Workspace pressHome() {
|
||||
try (LauncherInstrumentation.Closable e = eventsCheck()) {
|
||||
try (LauncherInstrumentation.Closable e = eventsCheck();
|
||||
LauncherInstrumentation.Closable c = addContextLayer("want to switch to home")) {
|
||||
waitForLauncherInitialized();
|
||||
// Click home, then wait for any accessibility event, then wait until accessibility
|
||||
// events stop.
|
||||
@@ -719,7 +720,7 @@ public final class LauncherInstrumentation {
|
||||
displaySize.x / 2, 0,
|
||||
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
|
||||
false, GestureScope.INSIDE_TO_OUTSIDE);
|
||||
try (LauncherInstrumentation.Closable c = addContextLayer(
|
||||
try (LauncherInstrumentation.Closable c1 = addContextLayer(
|
||||
"Swiped up from context menu to home")) {
|
||||
waitUntilLauncherObjectGone(CONTEXT_MENU_RES_ID);
|
||||
// Swiping up can temporarily bring Nexus Launcher if the current
|
||||
@@ -768,7 +769,7 @@ public final class LauncherInstrumentation {
|
||||
|| hasLauncherObject(OVERVIEW_RES_ID)),
|
||||
action);
|
||||
}
|
||||
try (LauncherInstrumentation.Closable c = addContextLayer(
|
||||
try (LauncherInstrumentation.Closable c1 = addContextLayer(
|
||||
"performed action to switch to Home - " + action)) {
|
||||
return getWorkspace();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user