Snap for 7553152 from fda82bde99 to tm-release

Change-Id: I5b8e37f6b79daaf8a9b7ec13b6314f010d7d753b
This commit is contained in:
Android Build Coastguard Worker
2021-07-16 03:08:20 +00:00
11 changed files with 276 additions and 99 deletions
@@ -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);
}
+6 -1
View File
@@ -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
+118 -37
View File
@@ -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();
}