Merge "Add debug log for initInputMonitor()" into sc-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index e46eb9e..9773366 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -29,6 +29,7 @@
<dimen name="overview_actions_bottom_margin_three_button">8dp</dimen>
<dimen name="overview_actions_horizontal_margin">16dp</dimen>
+ <dimen name="recents_row_spacing">48dp</dimen>
<dimen name="recents_page_spacing">16dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index aad7e17..0f13ef9 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -30,6 +30,7 @@
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
+import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
@@ -73,6 +74,8 @@
SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher));
SCRIM_MULTIPLIER.set(scrim, 1f);
getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
+ RECENTS_GRID_PROGRESS.set(mRecentsView, state.displayOverviewTasksAsGrid(mLauncher)
+ ? 1f : 0f);
}
@Override
@@ -117,6 +120,8 @@
mRecentsView, getTaskModalnessProperty(),
toState.getOverviewModalness(),
config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR));
+ setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS,
+ toState.displayOverviewTasksAsGrid(mLauncher) ? 1f : 0f, LINEAR);
}
abstract FloatProperty getTaskModalnessProperty();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 5ccc1e8..c9de662 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,7 +15,8 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
+import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
+import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
@@ -83,11 +84,14 @@
private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
LauncherState state) {
- float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0;
+ float clearAllButtonAlpha = (state.getVisibleElements(mLauncher) & CLEAR_ALL_BUTTON) != 0
+ ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
- buttonAlpha, LINEAR);
+ clearAllButtonAlpha, LINEAR);
+ float overviewButtonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0
+ ? 1 : 0;
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
- MultiValueAlpha.VALUE, buttonAlpha, config.getInterpolator(
+ MultiValueAlpha.VALUE, overviewButtonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index 2cf65af..2ad718b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -69,12 +69,18 @@
@Override
public int getVisibleElements(Launcher launcher) {
return super.getVisibleElements(launcher)
- & ~OVERVIEW_BUTTONS
+ & ~OVERVIEW_ACTIONS
+ & ~CLEAR_ALL_BUTTON
& ~VERTICAL_SWIPE_INDICATOR
| TASKBAR;
}
@Override
+ public boolean displayOverviewTasksAsGrid(Launcher launcher) {
+ return false;
+ }
+
+ @Override
public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
// Translate hotseat offscreen if we show it in overview.
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 41c689d..bdba482 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -45,7 +45,7 @@
@Override
public int getVisibleElements(Launcher launcher) {
- return OVERVIEW_BUTTONS;
+ return OVERVIEW_ACTIONS | CLEAR_ALL_BUTTON;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index b295e79..d480b6d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -28,6 +28,7 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
+import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -122,7 +123,8 @@
@Override
public int getVisibleElements(Launcher launcher) {
- return OVERVIEW_BUTTONS;
+ return displayOverviewTasksAsGrid(launcher) ? CLEAR_ALL_BUTTON
+ : CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS;
}
@Override
@@ -131,6 +133,11 @@
}
@Override
+ public boolean displayOverviewTasksAsGrid(Launcher launcher) {
+ return launcher.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
+ }
+
+ @Override
public String getDescription(Launcher launcher) {
return launcher.getString(R.string.accessibility_recent_apps);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index df433f8..4766870 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -18,7 +18,7 @@
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
+import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
@@ -222,7 +222,7 @@
mRecentsView.setContentAlpha(1);
mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
mLauncher.getActionsView().getVisibilityAlpha().setValue(
- (fromState.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1f : 0f);
+ (fromState.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 ? 1f : 0f);
float[] scaleAndOffset = toState.getOverviewScaleAndOffset(mLauncher);
// As we drag right, animate the following properties:
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
index 845699a..4df0f63 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
@@ -76,7 +76,7 @@
* @return the animation
*/
PendingAnimation createSwipeDownToTaskAppAnimation(long duration, Interpolator interpolator) {
- mRecentsView.setCurrentPage(mRecentsView.getPageNearestToCenterOfScreen());
+ mRecentsView.setCurrentPage(mRecentsView.getDestinationPage());
TaskView taskView = mRecentsView.getCurrentPageTaskView();
if (taskView == null) {
throw new IllegalStateException("There is no task view to animate to.");
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
index 6271a44..faf5054 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
@@ -31,6 +31,7 @@
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.AllAppsEduView;
/**
@@ -92,7 +93,8 @@
mLauncher.getDeviceProfile().isSeascape() == isDragTowardPositive;
return draggingFromNav ? OVERVIEW : NORMAL;
} else {
- return isDragTowardPositive ^ (fromState == OVERVIEW) ? OVERVIEW : NORMAL;
+ LauncherState startState = mStartState != null ? mStartState : fromState;
+ return isDragTowardPositive ^ (startState == OVERVIEW) ? OVERVIEW : NORMAL;
}
}
@@ -106,8 +108,8 @@
@Override
protected float getShiftRange() {
- return mLauncher.getDeviceProfile().isVerticalBarLayout()
- ? mLauncher.getDragLayer().getWidth() : super.getShiftRange();
+ // Should be in sync with TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT
+ return LayoutUtils.getDefaultSwipeHeight(mLauncher, mLauncher.getDeviceProfile());
}
@Override
@@ -116,7 +118,7 @@
long maxAccuracy = (long) (2 * range);
mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState,
maxAccuracy, animComponent);
- return (mLauncher.getDeviceProfile().isSeascape() ? 2 : -2) / range;
+ return (mLauncher.getDeviceProfile().isSeascape() ? 1 : -1) / range;
}
@Override
@@ -134,5 +136,6 @@
AllAppsEduView.show(mLauncher);
}
}
+ mStartState = null;
}
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 7a259d4..1bd7fe6 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
@@ -46,12 +45,14 @@
import static com.android.quickstep.GestureState.STATE_END_TARGET_SET;
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -79,6 +80,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -922,7 +924,7 @@
* MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
startShift = currentShift;
- interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
+ interpolator = endTarget == RECENTS ? ACCEL_DEACCEL : DEACCEL;
} else {
startShift = Utilities.boundToRange(currentShift - velocity.y
* getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
@@ -945,7 +947,7 @@
duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
if (endTarget == RECENTS) {
- interpolator = OVERSHOOT_1_2;
+ interpolator = ACCEL_DEACCEL;
}
}
}
@@ -958,7 +960,7 @@
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
} else if (endTarget == RECENTS) {
if (mRecentsView != null) {
- int nearestPage = mRecentsView.getPageNearestToCenterOfScreen();
+ int nearestPage = mRecentsView.getDestinationPage();
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.
@@ -1102,8 +1104,8 @@
homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
mLauncherTransitionController = null;
} else {
+ AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
- windowAnim.setDuration(duration).setInterpolator(interpolator);
windowAnim.addUpdateListener(valueAnimator -> {
computeRecentsScrollIfInvisible();
});
@@ -1138,8 +1140,15 @@
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
}
});
- windowAnim.start();
- mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
+ animatorSet.play(windowAnim);
+ if (mRecentsView != null && mDp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()
+ && mGestureState.getEndTarget() == RECENTS) {
+ animatorSet.play(ObjectAnimator.ofFloat(mRecentsView, RECENTS_GRID_PROGRESS, 1));
+ animatorSet.play(mTaskViewSimulator.gridProgress.animateToValue(0, 1));
+ }
+ animatorSet.setDuration(duration).setInterpolator(interpolator);
+ animatorSet.start();
+ mRunningWindowAnim = RunningWindowAnim.wrap(animatorSet);
}
}
@@ -1494,7 +1503,9 @@
@Override
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (mRecentsAnimationTargets.hasTask(task.taskId)) {
+ if (mRecentsView.getRunningTaskIndex() != -1
+ && mRecentsView.getRunningTaskId() == task.taskId
+ && mRecentsAnimationTargets.hasTask(task.taskId)) {
launchOtherTaskInLiveTileMode(task.taskId, mRecentsAnimationTargets.apps);
}
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
@@ -1759,7 +1770,7 @@
mTaskViewSimulator.getCurrentRect(),
mTaskViewSimulator.getCurrentCornerRadius());
LiveTileOverlay.INSTANCE.setRotation(
- mRecentsView.getPagedViewOrientedState().getDisplayRotation());
+ mTaskViewSimulator.getOrientationState().getDisplayRotation());
}
ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate();
}
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 25c0928..cd4f52f 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -31,6 +31,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
@@ -307,7 +308,11 @@
Animator launcherAnim;
final AnimatorListenerAdapter windowAnimEndListener;
if (launcherClosing) {
- launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
+ Context context = v.getContext();
+ DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
+ launcherAnim = dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()
+ ? ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, 0)
+ : recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index edce194..8c98480 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep.util;
+import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.deltaRotation;
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
@@ -24,6 +25,7 @@
import android.animation.TimeInterpolator;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
@@ -34,6 +36,7 @@
import androidx.annotation.NonNull;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
@@ -73,6 +76,7 @@
@NonNull
private RecentsOrientedState mOrientationState;
+ private final boolean mIsRecentsRtl;
private final Rect mTaskRect = new Rect();
private boolean mDrawsBelowRecents;
@@ -98,12 +102,15 @@
public final AnimatedFloat recentsViewScale = new AnimatedFloat();
public final AnimatedFloat fullScreenProgress = new AnimatedFloat();
public final AnimatedFloat recentsViewSecondaryTranslation = new AnimatedFloat();
+ public final AnimatedFloat gridProgress = new AnimatedFloat();
private final ScrollState mScrollState = new ScrollState();
// Cached calculations
private boolean mLayoutValid = false;
private boolean mScrollValid = false;
private int mOrientationStateId;
+ private final int mTaskThumbnailPadding;
+ private final int mRowSpacing;
public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
mContext = context;
@@ -113,6 +120,10 @@
mOrientationState.setGestureActive(true);
mCurrentFullscreenParams = new FullscreenDrawParams(context);
mOrientationStateId = mOrientationState.getStateId();
+ Resources resources = context.getResources();
+ mIsRecentsRtl = mOrientationState.getOrientationHandler().getRecentsRtlSetting(resources);
+ mTaskThumbnailPadding = (int) resources.getDimension(R.dimen.task_thumbnail_top_margin);
+ mRowSpacing = (int) resources.getDimension(R.dimen.recents_row_spacing);
}
/**
@@ -277,9 +288,10 @@
mScrollState.updateInterpolation(mDp, start);
}
- float progress = Utilities.boundToRange(fullScreenProgress.value, 0, 1);
+ float fullScreenProgress = Utilities.boundToRange(this.fullScreenProgress.value, 0, 1);
mCurrentFullscreenParams.setProgress(
- progress, recentsViewScale.value, mTaskRect.width(), mDp, mPositionHelper);
+ fullScreenProgress, recentsViewScale.value, mTaskRect.width(), mDp,
+ mPositionHelper);
// Apply thumbnail matrix
RectF insets = mCurrentFullscreenParams.mCurrentDrawnInsets;
@@ -291,6 +303,23 @@
mMatrix.postTranslate(insets.left, insets.top);
mMatrix.postScale(scale, scale);
+ float interpolatedGridProgress = ACCEL_DEACCEL.getInterpolation(gridProgress.value);
+
+ // Apply TaskView matrix: gridProgress
+ final int boxLength = (int) Math.max(taskWidth, taskHeight);
+ float availableHeight =
+ mTaskThumbnailPadding + taskHeight + mSizeStrategy.getOverviewActionsHeight(
+ mContext);
+ float rowHeight = (availableHeight - mRowSpacing) / 2;
+ float gridScale = rowHeight / (boxLength + mTaskThumbnailPadding);
+ scale = Utilities.mapRange(interpolatedGridProgress, 1f, gridScale);
+ mMatrix.postScale(scale, scale, mIsRecentsRtl ? 0 : taskWidth, 0);
+ float taskWidthDiff = taskWidth * (1 - gridScale);
+ float taskWidthOffset = mIsRecentsRtl ? taskWidthDiff : -taskWidthDiff;
+ float translationPrimary = Utilities.mapRange(interpolatedGridProgress, 0, taskWidthOffset);
+ mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
+ translationPrimary);
+
// Apply TaskView matrix: translate, scroll
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 0837300..9af4d30 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -43,9 +43,12 @@
private float mScrollAlpha = 1;
private float mContentAlpha = 1;
private float mVisibilityAlpha = 1;
+ private float mGridProgress = 1;
private boolean mIsRtl;
private final float mOriginalTranslationX, mOriginalTranslationY;
+ private float mNormalTranslationPrimary;
+ private float mGridTranslationPrimary;
private int mScrollOffset;
@@ -100,10 +103,18 @@
return;
}
- float shift = Math.min(scrollState.scrollFromEdge, orientationSize);
- float translation = mIsRtl ? (mScrollOffset - shift) : (mScrollOffset + shift);
- orientationHandler.setPrimaryAndResetSecondaryTranslate(
- this, translation, mOriginalTranslationX, mOriginalTranslationY);
+ float shift;
+ if (mIsRtl) {
+ shift = Math.min(scrollState.scrollFromEdge, orientationSize);
+ } else {
+ shift = Math.min(scrollState.scrollFromEdge,
+ orientationSize + getGridTrans(mGridTranslationPrimary))
+ - getGridTrans(mGridTranslationPrimary);
+ }
+ mNormalTranslationPrimary = mIsRtl ? (mScrollOffset - shift) : (mScrollOffset + shift);
+ applyPrimaryTranslation();
+ orientationHandler.getSecondaryViewTranslate().set(this,
+ orientationHandler.getSecondaryValue(mOriginalTranslationX, mOriginalTranslationY));
mScrollAlpha = 1 - shift / orientationSize;
updateAlpha();
}
@@ -111,6 +122,48 @@
private void updateAlpha() {
final float alpha = mScrollAlpha * mContentAlpha * mVisibilityAlpha;
setAlpha(alpha);
- setClickable(alpha == 1);
+ setClickable(Math.min(alpha, 1) == 1);
+ }
+
+ public void setGridTranslationPrimary(float gridTranslationPrimary) {
+ mGridTranslationPrimary = gridTranslationPrimary;
+ applyPrimaryTranslation();
+ }
+
+ public float getScrollAdjustment() {
+ float scrollAdjustment = 0;
+ if (mGridProgress > 0) {
+ scrollAdjustment += mGridTranslationPrimary;
+ }
+ return scrollAdjustment;
+ }
+
+ public float getOffsetAdjustment() {
+ return getScrollAdjustment();
+ }
+
+ /**
+ * Moves ClearAllButton between carousel and 2 row grid.
+ *
+ * @param gridProgress 0 = carousel; 1 = 2 row grid.
+ */
+ public void setGridProgress(float gridProgress) {
+ mGridProgress = gridProgress;
+ applyPrimaryTranslation();
+ }
+
+ private void applyPrimaryTranslation() {
+ RecentsView recentsView = getRecentsView();
+ if (recentsView == null) {
+ return;
+ }
+
+ PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
+ orientationHandler.getPrimaryViewTranslate().set(this,
+ mNormalTranslationPrimary + getGridTrans(mGridTranslationPrimary));
+ }
+
+ private float getGridTrans(float endTranslation) {
+ return mGridProgress > 0 ? endTranslation : 0;
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 52a7466..84218fd 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -16,9 +16,9 @@
package com.android.quickstep.views;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
+import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
@@ -169,7 +169,7 @@
if (enabled) {
LauncherState state = mActivity.getStateManager().getState();
boolean hasClearAllButton = (state.getVisibleElements(mActivity)
- & OVERVIEW_BUTTONS) != 0;
+ & CLEAR_ALL_BUTTON) != 0;
setDisallowScrollToClearAll(!hasClearAllButton);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 248fa46..e20540c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -107,6 +107,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
import com.android.launcher3.util.DynamicResource;
+import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.OverScroller;
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
@@ -239,6 +240,19 @@
}
};
+ public static final FloatProperty<RecentsView> RECENTS_GRID_PROGRESS =
+ new FloatProperty<RecentsView>("recentsGrid") {
+ @Override
+ public void setValue(RecentsView view, float gridProgress) {
+ view.setGridProgress(gridProgress);
+ }
+
+ @Override
+ public Float get(RecentsView view) {
+ return view.mGridProgress;
+ }
+ };
+
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface mSizeStrategy;
protected RecentsAnimationController mRecentsAnimationController;
@@ -264,6 +278,7 @@
private final float mFastFlingVelocity;
private final RecentsModel mModel;
private final int mTaskTopMargin;
+ private final int mRowSpacing;
private final ClearAllButton mClearAllButton;
private final Rect mClearAllButtonDeadZoneRect = new Rect();
private final Rect mTaskViewDeadZoneRect = new Rect();
@@ -285,6 +300,9 @@
private float mAdjacentPageOffset = 0;
private float mTaskViewsSecondaryTranslation = 0;
+ // Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
+ private float mGridProgress = 0;
+ private boolean mShowAsGrid;
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
@@ -450,6 +468,7 @@
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTaskTopMargin = getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
+ mRowSpacing = (int) getResources().getDimension(R.dimen.recents_row_spacing);
mSquaredTouchSlop = squaredTouchSlop(context);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@@ -479,6 +498,11 @@
mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
mLiveTileTaskViewSimulator.setOrientationState(mOrientationState);
mLiveTileTaskViewSimulator.setDrawsBelowRecents(true);
+
+ mShowAsGrid =
+ mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
+ mActivity.addOnDeviceProfileChangeListener(newDp ->
+ mShowAsGrid = newDp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get());
}
public OverScroller getScroller() {
@@ -640,8 +664,22 @@
}
public boolean isTaskViewVisible(TaskView tv) {
- // For now, just check if it's the active task or an adjacent task
- return Math.abs(indexOfChild(tv) - getNextPage()) <= 1;
+ if (mShowAsGrid) {
+ int screenStart = mOrientationHandler.getPrimaryScroll(this);
+ int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(this);
+ return isTaskViewWithinBounds(tv, screenStart, screenEnd);
+ } else {
+ // For now, just check if it's the active task or an adjacent task
+ return Math.abs(indexOfChild(tv) - getNextPage()) <= 1;
+ }
+ }
+
+ private boolean isTaskViewWithinBounds(TaskView tv, int start, int end) {
+ int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment();
+ int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment());
+ int taskEnd = taskStart + taskSize;
+ return (taskStart >= start && taskStart <= end) || (taskEnd >= start
+ && taskEnd <= end);
}
public TaskView getTaskView(int taskId) {
@@ -703,10 +741,21 @@
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
- TaskView taskView = getCurrentPageTaskView();
- if (taskView != null && taskView.offerTouchToChildren(ev)) {
- // Keep consuming events to pass to delegate
- return true;
+ if (mShowAsGrid) {
+ int taskCount = getTaskViewCount();
+ for (int i = 0; i < taskCount; i++) {
+ TaskView taskView = getTaskViewAt(i);
+ if (isTaskViewVisible(taskView) && taskView.offerTouchToChildren(ev)) {
+ // Keep consuming events to pass to delegate
+ return true;
+ }
+ }
+ } else {
+ TaskView taskView = getCurrentPageTaskView();
+ if (taskView != null && taskView.offerTouchToChildren(ev)) {
+ // Keep consuming events to pass to delegate
+ return true;
+ }
}
final int x = (int) ev.getX();
@@ -758,6 +807,11 @@
}
@Override
+ protected boolean snapToPageInFreeScroll() {
+ return !mShowAsGrid;
+ }
+
+ @Override
protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
// Enables swiping to the left or right only if the task overlay is not modal.
if (!isModal()) {
@@ -808,8 +862,8 @@
final Task task = tasks.get(i);
final TaskView taskView = (TaskView) getChildAt(pageIndex);
taskView.bind(task, mOrientationState);
- taskView.updateTaskSize(!taskView.hasTaskId(mRunningTaskId));
}
+ updateTaskSize();
if (mNextPage == INVALID_PAGE) {
// Set the current page to the running task, but not if settling on new task.
@@ -872,8 +926,6 @@
// Since we reuse the same mLiveTileTaskViewSimulator in the RecentsView, we need
// to reset the params after it settles in Overview from swipe up so that we don't
// render with obsolete param values.
- mLiveTileTaskViewSimulator.taskPrimaryTranslation.value = 0;
- mLiveTileTaskViewSimulator.taskSecondaryTranslation.value = 0;
mLiveTileTaskViewSimulator.fullScreenProgress.value = 0;
mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
@@ -899,12 +951,8 @@
public void setFullscreenProgress(float fullscreenProgress) {
mFullscreenProgress = fullscreenProgress;
int taskCount = getTaskViewCount();
- float accumulatedTranslationX = 0;
for (int i = 0; i < taskCount; i++) {
- TaskView taskView = getTaskViewAt(i);
- taskView.setFullscreenProgress(mFullscreenProgress);
- taskView.setAccumulatedTranslationX(accumulatedTranslationX);
- accumulatedTranslationX += taskView.getFullscreenTranslationX();
+ getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress);
}
// Fade out the actions view quickly (0.1 range)
@@ -941,11 +989,22 @@
dp.widthPx - mInsets.right - mTempRect.right,
dp.heightPx - mInsets.bottom - mTempRect.bottom);
// Force TaskView to update size from thumbnail
+ updateTaskSize();
+ }
+
+ /**
+ * Updates TaskView scaling and translation required to support variable width.
+ */
+ private void updateTaskSize() {
+ float accumulatedTranslationX = 0;
final int taskCount = getTaskViewCount();
for (int i = 0; i < taskCount; i++) {
TaskView taskView = getTaskViewAt(i);
- taskView.updateTaskSize(!taskView.hasTaskId(mRunningTaskId));
+ taskView.updateTaskSize();
+ taskView.setAccumulatedFullscreenTranslationX(accumulatedTranslationX);
+ accumulatedTranslationX += taskView.getFullscreenTranslationX();
}
+ updateGridProperties();
}
public void getTaskSize(Rect outRect) {
@@ -1010,6 +1069,31 @@
}
}
+ @Override
+ protected int getDestinationPage(int scaledScroll) {
+ if (mGridProgress == 0) {
+ return super.getDestinationPage(scaledScroll);
+ }
+
+ final int childCount = getChildCount();
+ if (mPageScrolls == null || childCount != mPageScrolls.length) {
+ return -1;
+ }
+
+ // When in grid, return the page which scroll is closest to screenStart instead of page
+ // nearest to center of screen.
+ int minDistanceFromScreenStart = Integer.MAX_VALUE;
+ int minDistanceFromScreenStartIndex = -1;
+ for (int i = 0; i < childCount; ++i) {
+ int distanceFromScreenStart = Math.abs(mPageScrolls[i] - scaledScroll);
+ if (distanceFromScreenStart < minDistanceFromScreenStart) {
+ minDistanceFromScreenStart = distanceFromScreenStart;
+ minDistanceFromScreenStartIndex = i;
+ }
+ }
+ return minDistanceFromScreenStartIndex;
+ }
+
/**
* Iterates through all the tasks, and loads the associated task data for newly visible tasks,
* and unloads the associated task data for tasks that are no longer visible.
@@ -1021,17 +1105,35 @@
return;
}
- int centerPageIndex = getPageNearestToCenterOfScreen();
- int numChildren = getChildCount();
- int lower = Math.max(0, centerPageIndex - 2);
- int upper = Math.min(centerPageIndex + 2, numChildren - 1);
+ int lower = 0;
+ int upper = 0;
+ int visibleStart = 0;
+ int visibleEnd = 0;
+ if (mShowAsGrid) {
+ int screenStart = mOrientationHandler.getPrimaryScroll(this);
+ int pageOrientedSize = mOrientationHandler.getMeasuredSize(this);
+ int halfScreenSize = pageOrientedSize / 2;
+ // Use +/- 50% screen width as visible area.
+ visibleStart = screenStart - halfScreenSize;
+ visibleEnd = screenStart + pageOrientedSize + halfScreenSize;
+ } else {
+ int centerPageIndex = getPageNearestToCenterOfScreen();
+ int numChildren = getChildCount();
+ lower = Math.max(0, centerPageIndex - 2);
+ upper = Math.min(centerPageIndex + 2, numChildren - 1);
+ }
// Update the task data for the in/visible children
for (int i = 0; i < getTaskViewCount(); i++) {
TaskView taskView = getTaskViewAt(i);
Task task = taskView.getTask();
int index = indexOfChild(taskView);
- boolean visible = lower <= index && index <= upper;
+ boolean visible;
+ if (mShowAsGrid) {
+ visible = isTaskViewWithinBounds(taskView, visibleStart, visibleEnd);
+ } else {
+ visible = lower <= index && index <= upper;
+ }
if (visible) {
if (task == mTmpRunningTask) {
// Skip loading if this is the task that we are animating into
@@ -1106,6 +1208,10 @@
}
}
+ public int getRunningTaskId() {
+ return mRunningTaskId;
+ }
+
public @Nullable TaskView getRunningTaskView() {
return getTaskView(mRunningTaskId);
}
@@ -1225,7 +1331,11 @@
}
setRunningTaskHidden(false);
animateUpRunningTaskIconScale();
- animateActionsViewIn();
+
+ // TODO: This should be tied to whether there is a focus app on overview.
+ if (!mShowAsGrid) {
+ animateActionsViewIn();
+ }
}
/**
@@ -1254,7 +1364,6 @@
// gesture and the task list is loaded and applied
mTmpRunningTask = Task.from(new TaskKey(runningTaskInfo), runningTaskInfo, false);
taskView.bind(mTmpRunningTask, mOrientationState);
- taskView.updateTaskSize(false);
// Measure and layout immediately so that the scroll values is updated instantly
// as the user might be quick-switching
@@ -1268,6 +1377,8 @@
setCurrentPage(getRunningTaskIndex());
setRunningTaskViewShowScreenshot(false);
setRunningTaskHidden(runningTaskTileHidden);
+ // Update task size after setting current task.
+ updateTaskSize();
// Reload the task list
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan);
@@ -1376,6 +1487,166 @@
}
}
+ /**
+ * Updates TaskView and ClearAllButton scaling and translation required to turn into grid
+ * layout.
+ * This method only calculates the potential position and depends on {@link #setGridProgress} to
+ * apply the actual scaling and translation.
+ */
+ private void updateGridProperties() {
+ int taskCount = getTaskViewCount();
+ if (taskCount == 0) {
+ return;
+ }
+
+ final int boxLength = Math.max(mTaskWidth, mTaskHeight);
+
+ float availableHeight =
+ mTaskTopMargin + mTaskHeight + mSizeStrategy.getOverviewActionsHeight(mContext);
+ float rowHeight = (availableHeight - mRowSpacing) / 2;
+ float gridScale = rowHeight / (boxLength + mTaskTopMargin);
+
+ TaskView firstTask = getTaskViewAt(0);
+ float firstTaskWidthOffset;
+ if (mIsRtl) {
+ // Move the first task to the right edge.
+ firstTaskWidthOffset = mTaskWidth - firstTask.getLayoutParams().width * gridScale;
+ } else {
+ // Move the first task to the left edge.
+ firstTaskWidthOffset = -firstTask.getLayoutParams().width * (1 - gridScale);
+ }
+
+ int topRowWidth = 0;
+ int bottomRowWidth = 0;
+ float topAccumulatedTranslationX = 0;
+ float bottomAccumulatedTranslationX = 0;
+ IntSet topSet = new IntSet();
+ float[] gridTranslations = new float[taskCount];
+ for (int i = 0; i < taskCount; i++) {
+ TaskView taskView = getTaskViewAt(i);
+ taskView.setGridScale(gridScale);
+
+ float taskWidthDiff = mTaskWidth - taskView.getLayoutParams().width * gridScale;
+ float taskWidthOffset = mIsRtl ? taskWidthDiff : -taskWidthDiff;
+ // Visually we want to move all task by firstTaskWidthOffset, but calculate page scroll
+ // according to right edge (or left in nonRtl) of TaskView.
+ gridTranslations[i] = firstTaskWidthOffset - taskWidthOffset;
+ taskView.setGridOffsetTranslationX(taskWidthOffset);
+
+ // Off-set gap due to task scaling.
+ float widthDiff = taskView.getLayoutParams().width * (1 - gridScale);
+ float gridScaleTranslationX = mIsRtl ? widthDiff : -widthDiff;
+ gridTranslations[i] += gridScaleTranslationX;
+
+ // Visible offset caused by having scaling pivot on top-right.
+ taskView.setNonRtlVisibleOffset(mIsRtl ? 0 : widthDiff);
+
+ if (topRowWidth <= bottomRowWidth) {
+ gridTranslations[i] += topAccumulatedTranslationX;
+ topRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing;
+ topSet.add(i);
+
+ taskView.setGridTranslationY(0);
+
+ // Move horizontally into empty space.
+ float widthOffset = 0;
+ for (int j = i - 1; !topSet.contains(j) && j >= 0; j--) {
+ widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale
+ + mPageSpacing;
+ }
+
+ float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
+ gridTranslations[i] += gridTranslationX;
+ topAccumulatedTranslationX += gridTranslationX + gridScaleTranslationX;
+ bottomAccumulatedTranslationX += gridScaleTranslationX;
+ } else {
+ gridTranslations[i] += bottomAccumulatedTranslationX;
+ bottomRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing;
+
+ // Move into bottom row.
+ float heightOffset = (boxLength + mTaskTopMargin) * gridScale + mRowSpacing;
+ taskView.setGridTranslationY(heightOffset);
+
+ // Move horizontally into empty space.
+ float widthOffset = 0;
+ for (int j = i - 1; topSet.contains(j); j--) {
+ widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale
+ + mPageSpacing;
+ }
+
+ float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
+ gridTranslations[i] += gridTranslationX;
+ topAccumulatedTranslationX += gridScaleTranslationX;
+ bottomAccumulatedTranslationX += gridTranslationX + gridScaleTranslationX;
+ }
+ }
+
+ // Use the accumulated translation of the longer row.
+ float clearAllAccumulatedTranslation = mIsRtl ? Math.max(topAccumulatedTranslationX,
+ bottomAccumulatedTranslationX) : Math.min(topAccumulatedTranslationX,
+ bottomAccumulatedTranslationX);
+
+ // If the last task is on the shorter row, ClearAllButton will embed into the shorter row
+ // which is not what we want. Compensate the width difference of the 2 rows in that case.
+ float shorterRowCompensation = 0;
+ if (topRowWidth <= bottomRowWidth) {
+ if (topSet.contains(taskCount - 1)) {
+ shorterRowCompensation = bottomRowWidth - topRowWidth;
+ }
+ } else {
+ if (!topSet.contains(taskCount - 1)) {
+ shorterRowCompensation = topRowWidth - bottomRowWidth;
+ }
+ }
+ float clearAllShorterRowCompensation =
+ mIsRtl ? -shorterRowCompensation : shorterRowCompensation;
+
+ // If the total width is shorter than one task's width, move ClearAllButton further away
+ // accordingly.
+ float clearAllShortTotalCompensation = 0;
+ float longRowWidth = Math.max(topRowWidth, bottomRowWidth);
+ if (longRowWidth < mTaskWidth) {
+ float shortTotalCompensation = mTaskWidth - longRowWidth;
+ clearAllShortTotalCompensation =
+ mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
+ }
+
+ float clearAllTotalTranslationX = firstTaskWidthOffset + clearAllAccumulatedTranslation
+ + clearAllShorterRowCompensation + clearAllShortTotalCompensation;
+
+ // We need to maintain first task's grid translation at 0, now shift translation of all
+ // the TaskViews to achieve that.
+ for (int i = 0; i < taskCount; i++) {
+ getTaskViewAt(i).setGridTranslationX(gridTranslations[i] - gridTranslations[0]);
+ }
+ mClearAllButton.setGridTranslationPrimary(clearAllTotalTranslationX - gridTranslations[0]);
+
+ setGridProgress(mGridProgress);
+ }
+
+ /**
+ * Moves TaskView and ClearAllButton between carousel and 2 row grid.
+ *
+ * @param gridProgress 0 = carousel; 1 = 2 row grid.
+ */
+ public void setGridProgress(float gridProgress) {
+ int taskCount = getTaskViewCount();
+ if (taskCount == 0) {
+ return;
+ }
+
+ if (!mShowAsGrid) {
+ gridProgress = 0;
+ }
+
+ mGridProgress = gridProgress;
+
+ for (int i = 0; i < taskCount; i++) {
+ getTaskViewAt(i).setGridProgress(gridProgress);
+ }
+ mClearAllButton.setGridProgress(gridProgress);
+ }
+
private void enableLayoutTransitions() {
if (mLayoutTransition == null) {
mLayoutTransition = new LayoutTransition();
@@ -1511,7 +1782,7 @@
if (animateTaskView) {
addDismissedTaskAnimations(taskView, duration, anim);
}
- } else {
+ } else if (!mShowAsGrid) { // Don't animate other tasks when dismissing in grid for now
// If we just take newScroll - oldScroll, everything to the right of dragged task
// translates to the left. We need to offset this in some cases:
// - In RTL, add page offset to all pages, since we want pages to move to the right
@@ -1604,6 +1875,8 @@
startHome();
} else {
snapToPageImmediately(pageToSnapTo);
+ // Grid got messed up, reapply.
+ updateGridProperties();
}
// Update the layout synchronously so that the position of next view is
// immediately available.
@@ -2379,17 +2652,16 @@
boolean pageScrollChanged = super.getPageScrolls(outPageScrolls, layoutChildren,
scrollLogic);
- final int taskCount = getTaskViewCount();
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- if (childCount < mTaskViewStartIndex) {
- continue;
+ View child = getChildAt(i);
+ float scrollDiff = 0;
+ if (child instanceof TaskView) {
+ scrollDiff = ((TaskView) child).getScrollAdjustment();
+ } else if (child instanceof ClearAllButton) {
+ scrollDiff = ((ClearAllButton) child).getScrollAdjustment();
}
- final TaskView taskView = getTaskViewAt(
- Utilities.boundToRange(i, mTaskViewStartIndex, taskCount - 1));
- float scrollDiff =
- taskView.getFullscreenTranslationX() + taskView.getAccumulatedTranslationX();
if (scrollDiff != 0) {
outPageScrolls[i] += scrollDiff;
pageScrollChanged = true;
@@ -2400,14 +2672,14 @@
@Override
protected int getChildOffset(int index) {
- if (index < mTaskViewStartIndex) {
- return super.getChildOffset(index);
+ int childOffset = super.getChildOffset(index);
+ View child = getChildAt(index);
+ if (child instanceof TaskView) {
+ childOffset += ((TaskView) child).getOffsetAdjustment();
+ } else if (child instanceof ClearAllButton) {
+ childOffset += ((ClearAllButton) child).getOffsetAdjustment();
}
-
- final TaskView taskView = getTaskViewAt(
- Utilities.boundToRange(index, mTaskViewStartIndex, getTaskViewCount() - 1));
- return super.getChildOffset(index) + (int) taskView.getFullscreenTranslationX()
- + (int) taskView.getAccumulatedTranslationX();
+ return childOffset;
}
@Override
@@ -2416,7 +2688,7 @@
if (taskView == null) {
return super.getChildVisibleSize(index);
}
- return super.getChildVisibleSize(index) - (int) taskView.getFullscreenTranslationX();
+ return (int) (super.getChildVisibleSize(index) * taskView.getSizeAdjustment());
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index e21bf76..f477ca7 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -38,6 +38,7 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.Themes;
@@ -113,7 +114,12 @@
// NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
// which would render the X and Y position set here incorrect
setPivotX(0);
- setPivotY(0);
+ if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
+ // In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
+ setPivotY(-mThumbnailTopMargin);
+ } else {
+ setPivotY(0);
+ }
setRotation(pagedOrientationHandler.getDegreesRotated());
setX(pagedOrientationHandler.getTaskMenuX(x, mTaskView.getThumbnail()));
setY(pagedOrientationHandler.getTaskMenuY(adjustedY, mTaskView.getThumbnail()));
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index dfbe6ce..20a8444 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -248,8 +248,9 @@
private IconView mIconView;
private final DigitalWellBeingToast mDigitalWellBeingToast;
private float mFullscreenProgress;
- private float mScaleAtFullscreen = 1;
+ private float mGridProgress;
private float mFullscreenScale = 1;
+ private float mGridScale = 1;
private final FullscreenDrawParams mCurrentFullscreenParams;
private final StatefulActivity mActivity;
@@ -262,8 +263,14 @@
private float mTaskResistanceTranslationY;
// The following translation variables should only be used in the same orientation as Launcher.
private float mFullscreenTranslationX;
- private float mAccumulatedTranslationX;
+ private float mAccumulatedFullscreenTranslationX;
private float mBoxTranslationY;
+ // The following grid translations scales with mGridProgress.
+ private float mGridTranslationX;
+ private float mGridTranslationY;
+ // Offset translation does not affect scroll calculation.
+ private float mGridOffsetTranslationX;
+ private float mNonRtlVisibleOffset;
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
@@ -722,7 +729,9 @@
@Override
public void onRecycle() {
- mFullscreenTranslationX = mAccumulatedTranslationX = mBoxTranslationY = 0f;
+ mFullscreenTranslationX = mAccumulatedFullscreenTranslationX = mGridTranslationX =
+ mGridTranslationY =
+ mGridOffsetTranslationX = mBoxTranslationY = mNonRtlVisibleOffset = 0f;
resetViewTransforms();
// Clear any references to the thumbnail (it will be re-read either from the cache or the
// system on next bind)
@@ -807,7 +816,7 @@
super.onLayout(changed, left, top, right, bottom);
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? (right - left) : 0);
- setPivotY(0);
+ setPivotY(mSnapshotView.getTop());
} else {
setPivotX((right - left) * 0.5f);
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
@@ -834,9 +843,31 @@
applyScale();
}
+ public void setGridScale(float gridScale) {
+ mGridScale = gridScale;
+ applyScale();
+ }
+
+ /**
+ * Moves TaskView between carousel and 2 row grid.
+ *
+ * @param gridProgress 0 = carousel; 1 = 2 row grid.
+ */
+ public void setGridProgress(float gridProgress) {
+ mGridProgress = gridProgress;
+ applyTranslationX();
+ applyTranslationY();
+ applyScale();
+ }
+
private void applyScale() {
- setScaleX(mFullscreenScale);
- setScaleY(mFullscreenScale);
+ float scale = 1;
+ float fullScreenProgress = EXAGGERATED_EASE.getInterpolation(mFullscreenProgress);
+ scale *= Utilities.mapRange(fullScreenProgress, 1f, mFullscreenScale);
+ float gridProgress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
+ scale *= Utilities.mapRange(gridProgress, 1f, mGridScale);
+ setScaleX(scale);
+ setScaleY(scale);
}
private void setDismissTranslationX(float x) {
@@ -878,13 +909,58 @@
return mFullscreenTranslationX;
}
- public void setAccumulatedTranslationX(float accumulatedTranslationX) {
- mAccumulatedTranslationX = accumulatedTranslationX;
+ public void setAccumulatedFullscreenTranslationX(float accumulatedFullscreenTranslationX) {
+ mAccumulatedFullscreenTranslationX = accumulatedFullscreenTranslationX;
applyTranslationX();
}
- public float getAccumulatedTranslationX() {
- return mAccumulatedTranslationX;
+ public void setGridTranslationX(float gridTranslationX) {
+ mGridTranslationX = gridTranslationX;
+ applyTranslationX();
+ }
+
+ public void setGridTranslationY(float gridTranslationY) {
+ mGridTranslationY = gridTranslationY;
+ applyTranslationY();
+ }
+
+ public void setGridOffsetTranslationX(float gridOffsetTranslationX) {
+ mGridOffsetTranslationX = gridOffsetTranslationX;
+ applyTranslationX();
+ }
+
+ public void setNonRtlVisibleOffset(float nonRtlVisibleOffset) {
+ mNonRtlVisibleOffset = nonRtlVisibleOffset;
+ }
+
+ public float getScrollAdjustment() {
+ float scrollAdjustment = 0;
+ if (mFullscreenProgress > 0) {
+ scrollAdjustment += mFullscreenTranslationX + mAccumulatedFullscreenTranslationX;
+ }
+ if (mGridProgress > 0) {
+ scrollAdjustment += mGridTranslationX;
+ }
+ return scrollAdjustment;
+ }
+
+ public float getOffsetAdjustment() {
+ float offsetAdjustment = getScrollAdjustment();
+ if (mGridProgress > 0) {
+ offsetAdjustment += mGridOffsetTranslationX + mNonRtlVisibleOffset;
+ }
+ return offsetAdjustment;
+ }
+
+ public float getSizeAdjustment() {
+ float sizeAdjustment = 1;
+ if (mFullscreenProgress > 0) {
+ sizeAdjustment *= mFullscreenScale;
+ }
+ if (mGridProgress > 0) {
+ sizeAdjustment *= mGridScale;
+ }
+ return sizeAdjustment;
}
private void setBoxTranslationY(float boxTranslationY) {
@@ -893,15 +969,20 @@
}
private void applyTranslationX() {
- setTranslationX(
- mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
- + mFullscreenTranslationX + mAccumulatedTranslationX);
+ setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
+ + getFullscreenTrans(mFullscreenTranslationX + mAccumulatedFullscreenTranslationX)
+ + getGridTrans(mGridTranslationX + mGridOffsetTranslationX));
}
private void applyTranslationY() {
setTranslationY(
mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
- + mBoxTranslationY);
+ + getGridTrans(mGridTranslationY) + mBoxTranslationY);
+ }
+
+ private float getGridTrans(float endTranslation) {
+ float progress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
+ return Utilities.mapRange(progress, 0, endTranslation);
}
public FloatProperty<TaskView> getFillDismissGapTranslationProperty() {
@@ -1057,7 +1138,9 @@
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
getThumbnail().getTaskOverlay().setFullscreenProgress(progress);
- updateTaskScaling();
+ applyTranslationX();
+ applyTranslationY();
+ applyScale();
TaskThumbnailView thumbnail = getThumbnail();
updateCurrentFullscreenParams(thumbnail.getPreviewPositionHelper());
@@ -1084,41 +1167,53 @@
previewPositionHelper);
}
- void updateTaskSize(boolean variableWidth) {
+ /**
+ * Updates TaskView scaling and translation required to support variable width if enabled, while
+ * ensuring TaskView fits into screen in fullscreen.
+ */
+ void updateTaskSize() {
ViewGroup.LayoutParams params = getLayoutParams();
- float thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio() : 0f;
- if (variableWidth && mActivity.getDeviceProfile().isTablet
- && FeatureFlags.ENABLE_OVERVIEW_GRID.get() && thumbnailRatio != 0f) {
+ if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
final int thumbnailPadding = (int) getResources().getDimension(
R.dimen.task_thumbnail_top_margin);
Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
int taskWidth = lastComputedTaskSize.width();
int taskHeight = lastComputedTaskSize.height();
- int boxLength = Math.max(taskWidth, taskHeight);
int expectedWidth;
int expectedHeight;
- if (thumbnailRatio > 1) {
- expectedWidth = boxLength;
- expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding;
+ float thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio() : 0f;
+ if (isRunningTask() || thumbnailRatio == 0f) {
+ expectedWidth = taskWidth;
+ expectedHeight = taskHeight + thumbnailPadding;
} else {
- expectedWidth = (int) (boxLength * thumbnailRatio);
- expectedHeight = boxLength + thumbnailPadding;
+ int boxLength = Math.max(taskWidth, taskHeight);
+ if (thumbnailRatio > 1) {
+ expectedWidth = boxLength;
+ expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding;
+ } else {
+ expectedWidth = (int) (boxLength * thumbnailRatio);
+ expectedHeight = boxLength + thumbnailPadding;
+ }
}
float heightDiff = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f;
setBoxTranslationY(heightDiff);
+ float fullscreenScale = 1f;
if (expectedWidth > taskWidth) {
// In full screen, expectedWidth should not be larger than taskWidth.
- mScaleAtFullscreen = taskWidth / (float) expectedWidth;
+ fullscreenScale = taskWidth / (float) expectedWidth;
} else if (expectedHeight - thumbnailPadding > taskHeight) {
// In full screen, expectedHeight should not be larger than taskHeight.
- mScaleAtFullscreen = taskHeight / (float) (expectedHeight - thumbnailPadding);
- } else {
- mScaleAtFullscreen = 1f;
+ fullscreenScale = taskHeight / (float) (expectedHeight - thumbnailPadding);
}
+ setFullscreenScale(fullscreenScale);
+
+ float widthDiff = params.width * (1 - mFullscreenScale);
+ setFullscreenTranslationX(
+ getLayoutDirection() == LAYOUT_DIRECTION_RTL ? -widthDiff : widthDiff);
if (params.width != expectedWidth || params.height != expectedHeight) {
params.width = expectedWidth;
@@ -1127,35 +1222,16 @@
}
} else {
setBoxTranslationY(0);
+ setFullscreenTranslationX(0);
+ setFullscreenScale(1);
if (params.width != ViewGroup.LayoutParams.MATCH_PARENT) {
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
setLayoutParams(params);
}
}
- updateTaskScaling();
}
- private void updateTaskScaling() {
- if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
- ViewGroup.LayoutParams params = getLayoutParams();
- if (params.width == ViewGroup.LayoutParams.MATCH_PARENT
- || params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
- // Snapshot is not loaded yet, skip.
- return;
- }
-
- float progress = EXAGGERATED_EASE.getInterpolation(mFullscreenProgress);
- setFullscreenScale(Utilities.mapRange(progress, 1f, mScaleAtFullscreen));
-
- float widthDiff = params.width * (1 - mFullscreenScale);
- setFullscreenTranslationX(getFullscreenTrans(
- getLayoutDirection() == LAYOUT_DIRECTION_RTL ? -widthDiff : widthDiff));
- } else {
- setFullscreenScale(1);
- setFullscreenTranslationX(0);
- }
- }
private float getFullscreenTrans(float endTranslation) {
float progress = ACCEL_DEACCEL.getInterpolation(mFullscreenProgress);
diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
index 72116eb..4ca1f59 100644
--- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java
@@ -49,7 +49,6 @@
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Background;
@@ -58,6 +57,7 @@
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.ui.TestViewHelpers;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.Before;
diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml
index 32a5419..1cdee08 100644
--- a/res/layout/folder_application.xml
+++ b/res/layout/folder_application.xml
@@ -21,4 +21,5 @@
android:textColor="?attr/folderTextColor"
android:includeFontPadding="false"
android:hapticFeedbackEnabled="false"
- launcher:iconDisplay="folder" />
+ launcher:iconDisplay="folder"
+ launcher:centerVertically="true" />
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index c230dad..d38a77a 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -27,15 +27,12 @@
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:paddingTop="16dp"
launcher:pageIndicator="@+id/folder_page_indicator" />
<LinearLayout
android:id="@+id/folder_footer"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="48dp"
android:clipChildren="false"
android:orientation="horizontal"
android:paddingLeft="12dp"
@@ -53,13 +50,10 @@
android:gravity="center_horizontal"
android:hint="@string/folder_hint_text"
android:imeOptions="flagNoExtractUi"
- android:paddingBottom="@dimen/folder_label_padding_bottom"
- android:paddingTop="@dimen/folder_label_padding_top"
android:singleLine="true"
android:textColor="?attr/folderTextColor"
android:textColorHighlight="?android:attr/colorControlHighlight"
- android:textColorHint="?attr/folderHintColor"
- android:textSize="@dimen/folder_label_text_size" />
+ android:textColorHint="?attr/folderHintColor"/>
<com.android.launcher3.pageindicators.PageIndicatorDots
android:id="@+id/folder_page_indicator"
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index c3e37e9..65a49ab 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -50,4 +50,14 @@
android:textSize="14sp"
android:alpha="0.8" />
+ <TextView
+ android:id="@+id/widget_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textSize="12sp"
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:fadingEdge="horizontal" />
+
</merge>
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 587df6d..4078ef4 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -133,6 +133,8 @@
<attr name="numAllAppsColumns" format="integer" />
<attr name="defaultLayoutId" format="reference" />
<attr name="demoModeLayoutId" format="reference" />
+ <attr name="isScalable" format="boolean" />
+
</declare-styleable>
<declare-styleable name="DevicePadding">
@@ -150,6 +152,12 @@
<attr name="minWidthDps" format="float" />
<attr name="minHeightDps" format="float" />
+ <!-- These min cell values are only used if GridDisplayOption#isScalable is true-->
+ <attr name="minCellHeightDps" format="float" />
+ <attr name="minCellWidthDps" format="float" />
+
+ <attr name="borderSpacingDps" format="float" />
+
<attr name="iconImageSize" format="float" />
<!-- landscapeIconSize defaults to iconSize, if not specified -->
<attr name="landscapeIconSize" format="float" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 41d1a12..89415b8 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -24,7 +24,7 @@
<!-- AllApps & Launcher transitions -->
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
- <integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
+ <integer name="config_workspaceSpringLoadShrinkPercentage">85</integer>
<!-- The duration of the animation from search hint to text entry -->
<integer name="config_searchHintAnimationDuration">50</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5f78192..3b171c6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -20,6 +20,7 @@
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_edge_margin">8dp</dimen>
+ <dimen name="dynamic_grid_left_right_margin">8dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
<!-- Minimum space between workspace and hotseat in spring loaded mode -->
<dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
@@ -27,7 +28,6 @@
<dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
<dimen name="dynamic_grid_cell_layout_padding">5.5dp</dimen>
<dimen name="dynamic_grid_cell_padding_x">8dp</dimen>
- <dimen name="dynamic_grid_cell_padding_y">7dp</dimen>
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_top_padding">8dp</dimen>
@@ -37,6 +37,9 @@
<dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
+ <!-- Scalable Grid -->
+ <dimen name="scalable_grid_left_right_margin">22dp</dimen>
+
<!-- Workspace page indicator -->
<dimen name="workspace_page_indicator_height">24dp</dimen>
<dimen name="workspace_page_indicator_line_height">1dp</dimen>
@@ -90,7 +93,6 @@
<!-- The size of corner radius of the arrow in the arrow toast. -->
<dimen name="arrow_toast_corner_radius">2dp</dimen>
-
<!-- Search bar in All Apps -->
<dimen name="all_apps_header_max_elevation">3dp</dimen>
<dimen name="all_apps_header_scroll_to_elevation">16dp</dimen>
@@ -148,10 +150,12 @@
<dimen name="folder_cell_x_padding">9dp</dimen>
<dimen name="folder_cell_y_padding">6dp</dimen>
- <dimen name="folder_child_text_size">13sp</dimen>
- <dimen name="folder_label_padding_top">12dp</dimen>
- <dimen name="folder_label_padding_bottom">12dp</dimen>
- <dimen name="folder_label_text_size">16sp</dimen>
+ <!-- label text size = workspace text size multiplied by this scale -->
+ <dimen name="folder_label_text_scale">1.14</dimen>
+ <dimen name="folder_label_height">48dp</dimen>
+
+ <dimen name="folder_content_padding_left_right">8dp</dimen>
+ <dimen name="folder_content_padding_top">16dp</dimen>
<!-- Sizes for managed profile badges -->
<dimen name="profile_badge_size">24dp</dimen>
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
index 4e811f3..936ce12 100644
--- a/robolectric_tests/config/robolectric.properties
+++ b/robolectric_tests/config/robolectric.properties
@@ -11,4 +11,4 @@
com.android.launcher3.shadows.ShadowOverrides \
com.android.launcher3.shadows.ShadowSurfaceTransactionApplier \
-application=com.android.launcher3.util.LauncherTestApplication
\ No newline at end of file
+application=com.android.launcher3.util.LauncherTestApplication
diff --git a/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
new file mode 100644
index 0000000..92f77f2
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Point;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public final class LauncherAppWidgetProviderInfoTest {
+
+ private static final int CELL_SIZE = 50;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void initSpans_minWidthSmallerThanCellWidth_shouldInitializeSpansToOne() {
+ LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
+ info.minWidth = 20;
+ info.minHeight = 20;
+ InvariantDeviceProfile idp = createIDP();
+
+ info.initSpans(mContext, idp);
+
+ assertThat(info.spanX).isEqualTo(1);
+ assertThat(info.spanY).isEqualTo(1);
+ }
+
+ @Test
+ public void initSpans_minWidthLargerThanCellWidth_shouldInitializeSpans() {
+ LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
+ info.minWidth = 80;
+ info.minHeight = 80;
+ InvariantDeviceProfile idp = createIDP();
+
+ info.initSpans(mContext, idp);
+
+ assertThat(info.spanX).isEqualTo(2);
+ assertThat(info.spanY).isEqualTo(2);
+ }
+
+ @Test
+ public void initSpans_minResizeWidthUnspecified_shouldInitializeMinSpansToOne() {
+ LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
+ InvariantDeviceProfile idp = createIDP();
+
+ info.initSpans(mContext, idp);
+
+ assertThat(info.minSpanX).isEqualTo(1);
+ assertThat(info.minSpanY).isEqualTo(1);
+ }
+
+ @Test
+ public void initSpans_minResizeWidthSmallerThanCellWidth_shouldInitializeMinSpansToOne() {
+ LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
+ info.minResizeWidth = 20;
+ info.minResizeHeight = 20;
+ InvariantDeviceProfile idp = createIDP();
+
+ info.initSpans(mContext, idp);
+
+ assertThat(info.minSpanX).isEqualTo(1);
+ assertThat(info.minSpanY).isEqualTo(1);
+ }
+
+ @Test
+ public void initSpans_minResizeWidthLargerThanCellWidth_shouldInitializeMinSpans() {
+ LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
+ info.minResizeWidth = 80;
+ info.minResizeHeight = 80;
+ InvariantDeviceProfile idp = createIDP();
+
+ info.initSpans(mContext, idp);
+
+ assertThat(info.minSpanX).isEqualTo(2);
+ assertThat(info.minSpanY).isEqualTo(2);
+ }
+
+ private InvariantDeviceProfile createIDP() {
+ DeviceProfile profile = Mockito.mock(DeviceProfile.class);
+ Mockito.when(profile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
+
+ InvariantDeviceProfile idp = new InvariantDeviceProfile();
+ idp.landscapeProfile = idp.portraitProfile = profile;
+ return idp;
+ }
+
+}
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
index 04797a6..b972c6f 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsDiffReporterTest.java
@@ -32,12 +32,12 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
index e94b253..a7c8d92 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java
@@ -31,13 +31,13 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
index ae5b9a5..848630e 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java
@@ -34,7 +34,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.ComponentWithLabel;
@@ -42,6 +41,7 @@
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.testing.TestActivity;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
import com.android.launcher3.widget.picker.WidgetsListHeaderViewHolderBinder.OnHeaderClickListener;
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 358e6e0..8a0cf34 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -37,7 +37,6 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BitmapInfo;
@@ -46,6 +45,7 @@
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.testing.TestActivity;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
index 86df3f8..2d22c45 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/model/WidgetsListContentEntryTest.java
@@ -26,11 +26,11 @@
import android.content.Context;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import org.junit.Before;
diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index 5922223..e68edd3 100644
--- a/robolectric_tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/robolectric_tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -30,11 +30,11 @@
import android.os.UserHandle;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.util.WidgetsTableUtils;
import org.junit.Before;
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index be92c5d..a813275 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -3,7 +3,6 @@
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
import static com.android.launcher3.Utilities.ATLEAST_S;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS;
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X;
import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y;
@@ -31,6 +30,7 @@
import com.android.launcher3.util.FocusLogic;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +50,14 @@
inv.portraitProfile.getCellSize()};
});
+ // Represents the border spacing size on the grid in the two orientations.
+ public static final MainThreadInitializedObject<int[]> BORDER_SPACING_SIZE =
+ new MainThreadInitializedObject<>(c -> {
+ InvariantDeviceProfile inv = LauncherAppState.getIDP(c);
+ return new int[] {inv.landscapeProfile.cellLayoutBorderSpacingPx,
+ inv.portraitProfile.cellLayoutBorderSpacingPx};
+ });
+
private static final int HANDLE_COUNT = 4;
private static final int INDEX_LEFT = 0;
private static final int INDEX_TOP = 1;
@@ -370,16 +378,12 @@
}
}
- private static PointF getWidgetSize(Context context, Point cellSize, int spanX, int spanY) {
+ private static PointF getWidgetSize(Context context, Point cellSize, int spanX, int spanY,
+ int borderSpacing) {
final float density = context.getResources().getDisplayMetrics().density;
- float hBorderSpacing = 0;
- float vBorderSpacing = 0;
- if (ENABLE_FOUR_COLUMNS.get()) {
- final int borderSpacing = context.getResources()
- .getDimensionPixelSize(R.dimen.dynamic_grid_cell_border_spacing);
- hBorderSpacing = (spanX - 1) * borderSpacing;
- vBorderSpacing = (spanY - 1) * borderSpacing;
- }
+ final float hBorderSpacing = (spanX - 1) * borderSpacing;
+ final float vBorderSpacing = (spanY - 1) * borderSpacing;
+
PointF widgetSize = new PointF();
widgetSize.x = ((spanX * cellSize.x) + hBorderSpacing) / density;
widgetSize.y = ((spanY * cellSize.y) + vBorderSpacing) / density;
@@ -389,10 +393,11 @@
/** Returns the actual widget size given its span. */
public static PointF getWidgetSize(Context context, int spanX, int spanY) {
final Point[] cellSize = CELL_SIZE.get(context);
+ final int[] borderSpacing = BORDER_SPACING_SIZE.get(context);
if (isLandscape(context)) {
- return getWidgetSize(context, cellSize[0], spanX, spanY);
+ return getWidgetSize(context, cellSize[0], spanX, spanY, borderSpacing[0]);
}
- return getWidgetSize(context, cellSize[1], spanX, spanY);
+ return getWidgetSize(context, cellSize[1], spanX, spanY, borderSpacing[1]);
}
/** Returns true if the screen is in landscape mode. */
@@ -404,9 +409,10 @@
/** Returns the list of sizes for a widget of given span, in dp. */
public static ArrayList<PointF> getWidgetSizes(Context context, int spanX, int spanY) {
final Point[] cellSize = CELL_SIZE.get(context);
+ final int[] borderSpacing = BORDER_SPACING_SIZE.get(context);
- PointF landSize = getWidgetSize(context, cellSize[0], spanX, spanY);
- PointF portSize = getWidgetSize(context, cellSize[1], spanX, spanY);
+ PointF landSize = getWidgetSize(context, cellSize[0], spanX, spanY, borderSpacing[0]);
+ PointF portSize = getWidgetSize(context, cellSize[1], spanX, spanY, borderSpacing[1]);
ArrayList<PointF> sizes = new ArrayList<>(2);
sizes.add(landSize);
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index b85c648..75e89b2 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -21,6 +21,7 @@
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
public class AppWidgetsRestoredReceiver extends BroadcastReceiver {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index ee4d7ec..e0be6de 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -17,7 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.FastBitmapDrawable.newIcon;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS;
import static com.android.launcher3.graphics.IconShape.getShape;
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
@@ -194,7 +193,7 @@
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
defaultIconSize = grid.iconSizePx;
- setCenterVertically(ENABLE_FOUR_COLUMNS.get());
+ setCenterVertically(grid.isScalableGrid);
} else if (mDisplay == DISPLAY_ALL_APPS) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 947388b..b8833cf 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -53,6 +53,7 @@
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -2663,20 +2664,21 @@
}
public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount,
- int rowCount, int borderSpacing) {
+ int rowCount, int borderSpacing, @Nullable Rect inset) {
setup(cellWidth, cellHeight, invertHorizontally, colCount, rowCount, 1.0f, 1.0f,
- borderSpacing);
+ borderSpacing, inset);
}
/**
- * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, int)},
+ * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, int, Rect)},
* if the view needs to be scaled.
*
* ie. In multi-window mode, we setup widgets so that they are measured and laid out
* using their full/invariant device profile sizes.
*/
public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount,
- int rowCount, float cellScaleX, float cellScaleY, int borderSpacing) {
+ int rowCount, float cellScaleX, float cellScaleY, int borderSpacing,
+ @Nullable Rect inset) {
if (isLockedToGrid) {
final int myCellHSpan = cellHSpan;
final int myCellVSpan = cellVSpan;
@@ -2697,6 +2699,13 @@
height = Math.round(myCellHeight) - topMargin - bottomMargin;
x = leftMargin + (myCellX * cellWidth) + (myCellX * borderSpacing);
y = topMargin + (myCellY * cellHeight) + (myCellY * borderSpacing);
+
+ if (inset != null) {
+ x -= inset.left;
+ y -= inset.top;
+ width += inset.left + inset.right;
+ height += inset.top + inset.bottom;
+ }
}
}
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 634093c..7beea74 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,7 +16,7 @@
package com.android.launcher3;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS;
+import static com.android.launcher3.ResourceUtils.pxFromDp;
import android.content.Context;
import android.content.res.Configuration;
@@ -66,6 +66,8 @@
public final float aspectRatio;
+ public final boolean isScalableGrid;
+
/**
* The maximum amount of left/right workspace padding as a percentage of the screen width.
* To be clear, this means that up to 7% of the screen width can be used as left padding, and
@@ -79,8 +81,10 @@
private static final int PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER = 4;
// Workspace
- public final int desiredWorkspaceLeftRightMarginPx;
- public final int cellLayoutBorderSpacingPx;
+ public final int desiredWorkspaceLeftRightOriginalPx;
+ public int desiredWorkspaceLeftRightMarginPx;
+ public final int cellLayoutBorderSpacingOriginalPx;
+ public int cellLayoutBorderSpacingPx;
public final int cellLayoutPaddingLeftRightPx;
public final int cellLayoutBottomPaddingPx;
public final int edgeMarginPx;
@@ -102,13 +106,21 @@
public int cellWidthPx;
public int cellHeightPx;
- public int cellYPaddingPx;
public int workspaceCellPaddingXPx;
+ public int cellYPaddingPx;
+ public int cellYPaddingOriginalPx;
+
// Folder
+ public float folderLabelTextScale;
+ public int folderLabelTextSizePx;
public int folderIconSizePx;
public int folderIconOffsetYPx;
+ // Folder content
+ public int folderContentPaddingLeftRight;
+ public int folderContentPaddingTop;
+
// Folder cell
public int folderCellWidthPx;
public int folderCellHeightPx;
@@ -164,9 +176,12 @@
this.inv = inv;
this.isLandscape = isLandscape;
this.isMultiWindowMode = isMultiWindowMode;
+ this.transposeLayoutWithOrientation = transposeLayoutWithOrientation;
windowX = windowPosition.x;
windowY = windowPosition.y;
+ isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
+
// Determine sizes.
widthPx = width;
heightPx = height;
@@ -193,8 +208,6 @@
boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
// Some more constants
- this.transposeLayoutWithOrientation = transposeLayoutWithOrientation;
-
context = getContext(context, info, isVerticalBarLayout()
? Configuration.ORIENTATION_LANDSCAPE
: Configuration.ORIENTATION_PORTRAIT);
@@ -217,16 +230,25 @@
availableHeightPx = nonFinalAvailableHeightPx;
edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
- desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : edgeMarginPx;
- cellYPaddingPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_y);
- cellLayoutBorderSpacingPx = isVerticalBarLayout()
- || isMultiWindowMode
- || !ENABLE_FOUR_COLUMNS.get()
- ? 0 : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_border_spacing);
+ desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : isScalableGrid
+ ? res.getDimensionPixelSize(R.dimen.scalable_grid_left_right_margin)
+ : res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
+ desiredWorkspaceLeftRightOriginalPx = desiredWorkspaceLeftRightMarginPx;
+
+ folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
+ folderContentPaddingLeftRight =
+ res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right);
+ folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top);
+
+ setCellLayoutBorderSpacing(pxFromDp(inv.borderSpacing, mInfo.metrics, 1f));
+ cellLayoutBorderSpacingOriginalPx = cellLayoutBorderSpacingPx;
+
int cellLayoutPaddingLeftRightMultiplier = !isVerticalBarLayout() && isTablet
? PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER : 1;
- int cellLayoutPadding = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
+ int cellLayoutPadding = isScalableGrid
+ ? 0
+ : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
if (isLandscape) {
cellLayoutPaddingLeftRightPx = 0;
cellLayoutBottomPaddingPx = cellLayoutPadding;
@@ -259,16 +281,16 @@
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
int hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
- hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, mInfo.metrics)
+ hotseatBarSizePx = pxFromDp(inv.iconSize, mInfo.metrics, 1f)
+ (isVerticalBarLayout()
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
: (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx
- + (ENABLE_FOUR_COLUMNS.get() ? 0 : hotseatExtraVerticalSize)));
+ + (isScalableGrid ? 0 : hotseatExtraVerticalSize)));
// Calculate all of the remaining variables.
int extraSpace = updateAvailableDimensions(res);
// Now that we have all of the variables calculated, we can tune certain sizes.
- if (ENABLE_FOUR_COLUMNS.get()) {
+ if (isScalableGrid) {
DevicePadding padding = inv.devicePaddings.getDevicePadding(extraSpace);
workspaceTopPadding = padding.getWorkspaceTopPadding(extraSpace);
workspaceBottomPadding = padding.getWorkspaceBottomPadding(extraSpace);
@@ -299,6 +321,30 @@
IconShape.DEFAULT_PATH_SIZE);
}
+ private void setCellLayoutBorderSpacing(int borderSpacing) {
+ if (isScalableGrid) {
+ cellLayoutBorderSpacingPx = borderSpacing;
+ folderContentPaddingLeftRight = borderSpacing;
+ folderContentPaddingTop = borderSpacing;
+ } else {
+ cellLayoutBorderSpacingPx = 0;
+ }
+ }
+
+ /**
+ * We inset the widget padding added by the system and instead rely on the border spacing
+ * between cells to create reliable consistency between widgets
+ */
+ public boolean shouldInsetWidgets() {
+ Rect widgetPadding = inv.defaultWidgetPadding;
+
+ // Check all sides to ensure that the widget won't overlap into another cell.
+ return cellLayoutBorderSpacingPx > widgetPadding.left
+ && cellLayoutBorderSpacingPx > widgetPadding.top
+ && cellLayoutBorderSpacingPx > widgetPadding.right
+ && cellLayoutBorderSpacingPx > widgetPadding.bottom;
+ }
+
public Builder toBuilder(Context context) {
Point size = new Point(availableWidthPx, availableHeightPx);
return new Builder(context, inv, mInfo)
@@ -380,20 +426,42 @@
private int updateAvailableDimensions(Resources res) {
updateIconSize(1f, res);
- // Check to see if the icons fit within the available height. If not, then scale down.
- float usedHeight = (cellHeightPx * inv.numRows)
- + (cellLayoutBorderSpacingPx * (inv.numRows - 1));
- int maxHeight = (availableHeightPx - getTotalWorkspacePadding().y);
+ Point workspacePadding = getTotalWorkspacePadding();
+
+ // Check to see if the icons fit within the available height.
+ float usedHeight = getCellLayoutHeight();
+ final int maxHeight = availableHeightPx - workspacePadding.y;
float extraHeight = Math.max(0, maxHeight - usedHeight);
- if (usedHeight > maxHeight) {
- float scale = maxHeight / usedHeight;
- updateIconSize(scale, res);
- extraHeight = 0;
+ float scaleY = maxHeight / usedHeight;
+ boolean shouldScale = scaleY < 1f;
+
+ float scaleX = 1f;
+ if (isScalableGrid) {
+ // We scale to fit the cellWidth and cellHeight in the available space.
+ // The benefit of scalable grids is that we can get consistent aspect ratios between
+ // devices.
+ float usedWidth = (cellWidthPx * inv.numColumns)
+ + (cellLayoutBorderSpacingPx * (inv.numColumns - 1))
+ + (desiredWorkspaceLeftRightMarginPx * 2);
+ // We do not subtract padding here, as we also scale the workspace padding if needed.
+ scaleX = availableWidthPx / usedWidth;
+ shouldScale = true;
}
+
+ if (shouldScale) {
+ float scale = Math.min(scaleX, scaleY);
+ updateIconSize(scale, res);
+ extraHeight = Math.max(0, maxHeight - getCellLayoutHeight());
+ }
+
updateAvailableFolderCellDimensions(res);
return Math.round(extraHeight);
}
+ private int getCellLayoutHeight() {
+ return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacingPx * (inv.numRows - 1));
+ }
+
/**
* Updating the iconSize affects many aspects of the launcher layout, such as: iconSizePx,
* iconTextSizePx, iconDrawablePaddingPx, cellWidth/Height, allApps* variants,
@@ -403,17 +471,21 @@
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
float invIconSizeDp = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
- iconSizePx = Math.max(1, (int) (ResourceUtils.pxFromDp(invIconSizeDp, mInfo.metrics)
- * scale));
- iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, mInfo.metrics) * scale);
+ iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale));
+ iconTextSizePx = pxFromDp(inv.iconTextSize, mInfo.metrics, scale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
- if (ENABLE_FOUR_COLUMNS.get()) {
- cellHeightPx = iconSizePx + iconDrawablePaddingPx
- + Utilities.calculateTextHeight(iconTextSizePx)
- + (cellYPaddingPx * 2);
+ setCellLayoutBorderSpacing((int) (cellLayoutBorderSpacingOriginalPx * scale));
+
+ if (isScalableGrid) {
+ cellWidthPx = pxFromDp(inv.minCellWidth, mInfo.metrics, scale);
+ cellHeightPx = pxFromDp(inv.minCellHeight, mInfo.metrics, scale);
+ int cellContentHeight = iconSizePx + iconDrawablePaddingPx
+ + Utilities.calculateTextHeight(iconTextSizePx);
+ cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
+ desiredWorkspaceLeftRightMarginPx = (int) (desiredWorkspaceLeftRightOriginalPx * scale);
} else {
- cellYPaddingPx = 0;
+ cellWidthPx = iconSizePx + iconDrawablePaddingPx;
cellHeightPx = iconSizePx + iconDrawablePaddingPx
+ Utilities.calculateTextHeight(iconTextSizePx);
int cellPaddingY = (getCellSize().y - cellHeightPx) / 2;
@@ -426,11 +498,10 @@
iconDrawablePaddingPx = cellPaddingY;
}
}
- cellWidthPx = iconSizePx + iconDrawablePaddingPx;
// All apps
if (allAppsHasDifferentNumColumns()) {
- allAppsIconSizePx = ResourceUtils.pxFromDp(inv.allAppsIconSize, mInfo.metrics);
+ allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mInfo.metrics);
allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mInfo.metrics);
allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
// We use 4 below to ensure labels are closer to their corresponding icon.
@@ -474,12 +545,10 @@
}
private void updateAvailableFolderCellDimensions(Resources res) {
- int folderBottomPanelSize = res.getDimensionPixelSize(R.dimen.folder_label_padding_top)
- + res.getDimensionPixelSize(R.dimen.folder_label_padding_bottom)
- + Utilities.calculateTextHeight(res.getDimension(R.dimen.folder_label_text_size));
-
updateFolderCellSize(1f, res);
+ final int folderBottomPanelSize = res.getDimensionPixelSize(R.dimen.folder_label_height);
+
// Don't let the folder get too close to the edges of the screen.
int folderMargin = edgeMarginPx * 2;
Point totalWorkspacePadding = getTotalWorkspacePadding();
@@ -488,13 +557,14 @@
float contentUsedHeight = folderCellHeightPx * inv.numFolderRows
+ ((inv.numFolderRows - 1) * cellLayoutBorderSpacingPx);
int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y - folderBottomPanelSize
- - folderMargin;
+ - folderMargin - folderContentPaddingTop;
float scaleY = contentMaxHeight / contentUsedHeight;
// Check if the icons fit within the available width.
float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns
+ ((inv.numFolderColumns - 1) * cellLayoutBorderSpacingPx);
- int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin;
+ int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin
+ - folderContentPaddingLeftRight * 2;
float scaleX = contentMaxWidth / contentUsedWidth;
float scale = Math.min(scaleX, scaleY);
@@ -504,9 +574,10 @@
}
private void updateFolderCellSize(float scale, Resources res) {
- folderChildIconSizePx = (int) (ResourceUtils.pxFromDp(inv.iconSize, mInfo.metrics) * scale);
- folderChildTextSizePx =
- (int) (res.getDimensionPixelSize(R.dimen.folder_child_text_size) * scale);
+ float invIconSizeDp = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize;
+ folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale));
+ folderChildTextSizePx = pxFromDp(inv.iconTextSize, mInfo.metrics, scale);
+ folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
int cellPaddingX = (int) (res.getDimensionPixelSize(R.dimen.folder_cell_x_padding) * scale);
@@ -588,7 +659,7 @@
} else {
// Pad the top and bottom of the workspace with search/hotseat bar sizes
padding.set(desiredWorkspaceLeftRightMarginPx,
- workspaceTopPadding + edgeMarginPx,
+ workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx),
desiredWorkspaceLeftRightMarginPx,
paddingBottom);
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 2a08c50..bb60557 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -111,6 +111,10 @@
public float allAppsIconSize;
public float allAppsIconTextSize;
+ public float minCellHeight;
+ public float minCellWidth;
+ public float borderSpacing;
+
private SparseArray<TypedValue> mExtraAttrs;
/**
@@ -123,6 +127,11 @@
*/
public int numAllAppsColumns;
+ /**
+ * Do not query directly. see {@link DeviceProfile#isScalableGrid}.
+ */
+ protected boolean isScalable;
+
public String dbFile;
public int defaultLayoutId;
int demoModeLayoutId;
@@ -154,6 +163,10 @@
iconTextSize = p.iconTextSize;
numHotseatIcons = p.numHotseatIcons;
numAllAppsColumns = p.numAllAppsColumns;
+ isScalable = p.isScalable;
+ minCellHeight = p.minCellHeight;
+ minCellWidth = p.minCellWidth;
+ borderSpacing = p.borderSpacing;
dbFile = p.dbFile;
allAppsIconSize = p.allAppsIconSize;
allAppsIconTextSize = p.allAppsIconTextSize;
@@ -213,6 +226,9 @@
result.landscapeIconSize = defaultDisplayOption.landscapeIconSize;
result.allAppsIconSize = Math.min(
defaultDisplayOption.allAppsIconSize, myDisplayOption.allAppsIconSize);
+ result.minCellHeight = defaultDisplayOption.minCellHeight;
+ result.minCellWidth = defaultDisplayOption.minCellWidth;
+ result.borderSpacing = defaultDisplayOption.borderSpacing;
devicePaddings = new DevicePaddings(context);
initGrid(context, myInfo, result);
@@ -259,6 +275,7 @@
numFolderRows = closestProfile.numFolderRows;
numFolderColumns = closestProfile.numFolderColumns;
numAllAppsColumns = closestProfile.numAllAppsColumns;
+ isScalable = closestProfile.isScalable;
mExtraAttrs = closestProfile.extraAttrs;
@@ -269,6 +286,10 @@
iconTextSize = displayOption.iconTextSize;
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
+ minCellHeight = displayOption.minCellHeight;
+ minCellWidth = displayOption.minCellWidth;
+ borderSpacing = displayOption.borderSpacing;
+
if (Utilities.isGridOptionsEnabled(context)) {
allAppsIconSize = displayOption.allAppsIconSize;
allAppsIconTextSize = displayOption.allAppsIconTextSize;
@@ -589,6 +610,8 @@
private final int defaultLayoutId;
private final int demoModeLayoutId;
+ private final boolean isScalable;
+
private final SparseArray<TypedValue> extraAttrs;
public GridOption(Context context, AttributeSet attrs) {
@@ -612,6 +635,9 @@
numAllAppsColumns = a.getInt(
R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
+ isScalable = a.getBoolean(
+ R.styleable.GridDisplayOption_isScalable, false);
+
a.recycle();
extraAttrs = Themes.createValueMap(context, attrs,
@@ -626,6 +652,10 @@
private final float minHeightDps;
private final boolean canBeDefault;
+ private float minCellHeight;
+ private float minCellWidth;
+ private float borderSpacing;
+
private float iconSize;
private float iconTextSize;
private float landscapeIconSize;
@@ -643,6 +673,10 @@
canBeDefault = a.getBoolean(
R.styleable.ProfileDisplayOption_canBeDefault, false);
+ minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
+ minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
+ borderSpacing = a.getFloat(R.styleable.ProfileDisplayOption_borderSpacingDps, 0);
+
iconSize = a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0);
landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize,
iconSize);
@@ -664,6 +698,9 @@
minWidthDps = 0;
minHeightDps = 0;
canBeDefault = false;
+ minCellHeight = 0;
+ minCellWidth = 0;
+ borderSpacing = 0;
}
private DisplayOption multiply(float w) {
@@ -672,6 +709,9 @@
allAppsIconSize *= w;
iconTextSize *= w;
allAppsIconTextSize *= w;
+ minCellHeight *= w;
+ minCellWidth *= w;
+ borderSpacing *= w;
return this;
}
@@ -681,6 +721,9 @@
allAppsIconSize += p.allAppsIconSize;
iconTextSize += p.iconTextSize;
allAppsIconTextSize += p.allAppsIconTextSize;
+ minCellHeight += p.minCellHeight;
+ minCellWidth += p.minCellWidth;
+ borderSpacing += p.borderSpacing;
return this;
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index f7ff262..253a7c7 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -181,7 +181,9 @@
import com.android.launcher3.views.FloatingSurfaceView;
import com.android.launcher3.views.OptionsPopupView;
import com.android.launcher3.views.ScrimView;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.PendingAppWidgetHostView;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index e151777..2ec5e90 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -71,6 +71,7 @@
import com.android.launcher3.util.NoLocaleSQLiteHelper;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
import org.xmlpull.v1.XmlPullParser;
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index f9a1ded..781f171 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -56,8 +56,9 @@
public static final int ALL_APPS_HEADER_EXTRA = 1 << 3; // e.g. app predictions
public static final int ALL_APPS_CONTENT = 1 << 4;
public static final int VERTICAL_SWIPE_INDICATOR = 1 << 5;
- public static final int OVERVIEW_BUTTONS = 1 << 6;
+ public static final int OVERVIEW_ACTIONS = 1 << 6;
public static final int TASKBAR = 1 << 7;
+ public static final int CLEAR_ALL_BUTTON = 1 << 8;
/** Mask of all the items that are contained in the apps view. */
public static final int APPS_VIEW_ITEM_MASK =
@@ -221,6 +222,13 @@
}
/**
+ * For this state, whether tasks should layout as a grid rather than a list.
+ */
+ public boolean displayOverviewTasksAsGrid(Launcher launcher) {
+ return false;
+ }
+
+ /**
* The amount of blur and wallpaper zoom to apply to the background of either the app
* or Launcher surface in this state. Should be a number between 0 and 1, inclusive.
*
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index af2d94a..c6766a4 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -219,7 +219,7 @@
/**
* Returns the index of the currently displayed page. When in free scroll mode, this is the page
* that the user was on before entering free scroll mode (e.g. the home screen page they
- * long-pressed on to enter the overview). Try using {@link #getPageNearestToCenterOfScreen()}
+ * long-pressed on to enter the overview). Try using {@link #getDestinationPage()}
* to get the page the user is currently scrolling over.
*/
public int getCurrentPage() {
@@ -1289,7 +1289,7 @@
if (((initialScroll >= maxScroll) && (isVelocityLeft || !isFling)) ||
((initialScroll <= minScroll) && (!isVelocityLeft || !isFling))) {
mScroller.springBack(initialScroll, minScroll, maxScroll);
- mNextPage = getPageNearestToCenterOfScreen();
+ mNextPage = getDestinationPage();
} else {
mScroller.setInterpolator(mDefaultInterpolator);
mScroller.fling(initialScroll, -velocity,
@@ -1297,11 +1297,12 @@
Math.round(getWidth() * 0.5f * OVERSCROLL_DAMP_FACTOR));
int finalPos = mScroller.getFinalPos();
- mNextPage = getPageNearestToCenterOfScreen(finalPos);
+ mNextPage = getDestinationPage(finalPos);
int firstPageScroll = getScrollForPage(!mIsRtl ? 0 : getPageCount() - 1);
int lastPageScroll = getScrollForPage(!mIsRtl ? getPageCount() - 1 : 0);
- if (finalPos > minScroll && finalPos < maxScroll) {
+ if (snapToPageInFreeScroll() && finalPos > minScroll
+ && finalPos < maxScroll) {
// If scrolling ends in the half of the added space that is closer to
// the end, settle to the end. Otherwise snap to the nearest page.
// If flinging past one of the ends, don't change the velocity as it
@@ -1347,6 +1348,10 @@
return true;
}
+ protected boolean snapToPageInFreeScroll() {
+ return true;
+ }
+
protected boolean shouldFlingForVelocity(int velocity) {
float threshold = mAllowEasyFling ? mEasyFlingThresholdVelocity : mFlingThresholdVelocity;
return Math.abs(velocity) > threshold;
@@ -1452,6 +1457,14 @@
}
}
+ public int getDestinationPage() {
+ return getDestinationPage(mOrientationHandler.getPrimaryScroll(this));
+ }
+
+ protected int getDestinationPage(int scaledScroll) {
+ return getPageNearestToCenterOfScreen(scaledScroll);
+ }
+
public int getPageNearestToCenterOfScreen() {
return getPageNearestToCenterOfScreen(mOrientationHandler.getPrimaryScroll(this));
}
@@ -1487,7 +1500,7 @@
}
protected void snapToDestination() {
- snapToPage(getPageNearestToCenterOfScreen(), getPageSnapDuration());
+ snapToPage(getDestinationPage(), getPageSnapDuration());
}
protected boolean isInOverScroll() {
diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java
index f60e1f8..ece123d 100644
--- a/src/com/android/launcher3/ResourceUtils.java
+++ b/src/com/android/launcher3/ResourceUtils.java
@@ -60,7 +60,11 @@
}
public static int pxFromDp(float size, DisplayMetrics metrics) {
- return size < 0 ? INVALID_RESOURCE_HANDLE : Math.round(
- TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics));
+ return pxFromDp(size, metrics, 1f);
+ }
+
+ public static int pxFromDp(float size, DisplayMetrics metrics, float scale) {
+ return size < 0 ? INVALID_RESOURCE_HANDLE : Math.round(scale
+ * TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics));
}
}
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 7276887..4fd87cb 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -46,6 +46,7 @@
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import java.net.URISyntaxException;
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index eab8272..2c24c3a 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -37,6 +37,8 @@
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private final int[] mTmpCellXY = new int[2];
+ private final Rect mTempRect = new Rect();
+
@ContainerType
private final int mContainerType;
private final WallpaperManager mWallpaperManager;
@@ -101,11 +103,12 @@
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if (child instanceof LauncherAppWidgetHostView) {
DeviceProfile profile = mActivity.getDeviceProfile();
+ ((LauncherAppWidgetHostView) child).getWidgetInset(profile, mTempRect);
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpacing);
+ profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpacing, mTempRect);
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- mBorderSpacing);
+ mBorderSpacing, null);
}
}
@@ -124,12 +127,12 @@
final DeviceProfile profile = mActivity.getDeviceProfile();
if (child instanceof LauncherAppWidgetHostView) {
+ ((LauncherAppWidgetHostView) child).getWidgetInset(profile, mTempRect);
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpacing);
- // Widgets have their own padding
+ profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpacing, mTempRect);
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- mBorderSpacing);
+ mBorderSpacing, null);
// Center the icon/folder
int cHeight = getCellContentHeight();
int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f));
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 2c45c77..446c873 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -50,6 +50,7 @@
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SQLiteCacheHelper;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.WidgetManagerHelper;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2528c03..981ead9 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -63,7 +63,6 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;
-import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.anim.Interpolators;
@@ -104,6 +103,8 @@
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.WallpaperOffsetInterpolator;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -416,7 +417,7 @@
// widgets as they cannot be placed inside a folder.
// Start at the current page and search right (on LTR) until finding a page with
// enough space. Since an empty screen is the furthest right, a page must be found.
- int currentPage = getPageNearestToCenterOfScreen();
+ int currentPage = getDestinationPage();
for (int pageIndex = currentPage; pageIndex < getPageCount(); pageIndex++) {
CellLayout page = (CellLayout) getPageAt(pageIndex);
if (page.hasReorderSolution(dragObject.dragInfo)) {
diff --git a/src/com/android/launcher3/allapps/search/LiveSearchManager.java b/src/com/android/launcher3/allapps/search/LiveSearchManager.java
index 4ef154e..76099a6 100644
--- a/src/com/android/launcher3/allapps/search/LiveSearchManager.java
+++ b/src/com/android/launcher3/allapps/search/LiveSearchManager.java
@@ -43,11 +43,11 @@
import androidx.slice.SliceViewManager.SliceCallback;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import java.util.ArrayList;
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 77d2b85..5dc94ff 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -47,8 +47,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetHost;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.ItemInstallQueue;
@@ -56,6 +54,8 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.PinRequestHelper;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
diff --git a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
index 7788f93..0a1aba1 100644
--- a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
+++ b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
@@ -65,6 +65,9 @@
}
public Runnable getFlingAnimation(DropTarget.DragObject dragObject, DragOptions options) {
+ if (options == null) {
+ return null;
+ }
PointF vel = isFlingingToDelete();
options.isFlingToDelete = vel != null;
if (!options.isFlingToDelete) {
diff --git a/src/com/android/launcher3/dragndrop/LivePreviewWidgetCell.java b/src/com/android/launcher3/dragndrop/LivePreviewWidgetCell.java
index be6a07f..fa062f5 100644
--- a/src/com/android/launcher3/dragndrop/LivePreviewWidgetCell.java
+++ b/src/com/android/launcher3/dragndrop/LivePreviewWidgetCell.java
@@ -12,10 +12,10 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetCell;
/**
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index 6104d80..2290473 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -30,8 +30,8 @@
import com.android.launcher3.DragSource;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.PendingItemDragHelper;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 504b29e..bcb3a54 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -44,6 +44,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
+import android.util.TypedValue;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -246,11 +247,16 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ final DeviceProfile dp = mLauncher.getDeviceProfile();
+ final int paddingLeftRight = dp.folderContentPaddingLeftRight;
+
mContent = findViewById(R.id.folder_content);
+ mContent.setPadding(paddingLeftRight, dp.folderContentPaddingTop, paddingLeftRight, 0);
mContent.setFolder(this);
mPageIndicator = findViewById(R.id.folder_page_indicator);
mFolderName = findViewById(R.id.folder_name);
+ mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
mFolderName.setOnBackKeyListener(this);
mFolderName.setOnFocusChangeListener(this);
mFolderName.setOnEditorActionListener(this);
@@ -262,12 +268,7 @@
mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);
-
- // We find out how tall footer wants to be (it is set to wrap_content), so that
- // we can allocate the appropriate amount of space for it.
- int measureSpec = MeasureSpec.UNSPECIFIED;
- mFooter.measure(measureSpec, measureSpec);
- mFooterHeight = mFooter.getMeasuredHeight();
+ mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
if (Utilities.ATLEAST_R) {
mFolderWindowInsetsAnimationCallback =
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 1cac31e..feb528c 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -324,7 +324,9 @@
final int previewPosX =
(int) ((mTmpParams.transX - iconOffsetX + previewItemOffsetX) / folderScale);
- final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY) / folderScale);
+ final float paddingTop = btv.getPaddingTop() * iconScale;
+ final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY - paddingTop)
+ / folderScale);
final float xDistance = previewPosX - btvLp.x;
final float yDistance = previewPosY - btvLp.y;
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 3a9986e..5e9b179 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -58,7 +58,6 @@
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -91,6 +90,7 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index e8a52bd..804e72e 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -25,7 +25,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
@@ -40,6 +39,7 @@
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import java.util.ArrayList;
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index 79467d3..c6c0791 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -39,7 +39,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.LauncherPreviewRenderer;
@@ -48,6 +47,7 @@
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import java.util.ArrayList;
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index d09bf81..df8367f 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -42,7 +42,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -52,6 +51,7 @@
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PersistedItemArray;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import java.util.HashSet;
import java.util.List;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 8438622..209c5be 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -45,12 +45,12 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.TimingLogger;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
@@ -87,6 +87,7 @@
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import java.util.ArrayList;
@@ -126,7 +127,7 @@
private final UserManagerState mUserManagerState = new UserManagerState();
- protected Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap;
+ protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();
private boolean mStopped;
@@ -664,12 +665,13 @@
final boolean wasProviderReady = !c.hasRestoreFlag(
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
- if (mWidgetProvidersMap == null) {
- mWidgetProvidersMap = WidgetManagerHelper.getAllProvidersMap(
- context);
+ ComponentKey providerKey = new ComponentKey(component, c.user);
+ if (!mWidgetProvidersMap.containsKey(providerKey)) {
+ mWidgetProvidersMap.put(providerKey,
+ widgetHelper.findProvider(component, c.user));
}
- final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(
- new ComponentKey(component, c.user));
+ final AppWidgetProviderInfo provider =
+ mWidgetProvidersMap.get(providerKey);
final boolean isProviderReady = isValidProvider(provider);
if (!isSafeMode && !customWidget &&
@@ -873,7 +875,6 @@
mBgDataModel.itemsIdMap.remove(folderId);
}
}
-
// Remove any ghost widgets
LauncherSettings.Settings.call(contentResolver,
LauncherSettings.Settings.METHOD_REMOVE_GHOST_WIDGETS);
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index f7b43d6..312435d 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -28,7 +28,6 @@
import android.util.Log;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
@@ -43,6 +42,7 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/com/android/launcher3/model/WidgetItem.java b/src/com/android/launcher3/model/WidgetItem.java
index de2481a..97071bb 100644
--- a/src/com/android/launcher3/model/WidgetItem.java
+++ b/src/com/android/launcher3/model/WidgetItem.java
@@ -4,11 +4,11 @@
import android.content.pm.PackageManager;
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
/**
* An wrapper over various items displayed in a widget picker,
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 65df614..b28d6f7 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -67,8 +67,9 @@
/**
* Play an atomic recents animation when the progress from NORMAL to OVERVIEW reaches this.
+ * TODO: Remove the atomic animation altogether and just go to OVERVIEW directly (b/175137718).
*/
- public static final float ATOMIC_OVERVIEW_ANIM_THRESHOLD = 0.5f;
+ public static final float ATOMIC_OVERVIEW_ANIM_THRESHOLD = 1f;
protected final long ATOMIC_DURATION = getAtomicDuration();
protected final Launcher mLauncher;
@@ -342,9 +343,7 @@
if (!goingBetweenNormalAndOverview(fromState, toState)) {
return;
}
- float threshold = toState == OVERVIEW ? ATOMIC_OVERVIEW_ANIM_THRESHOLD
- : 1f - ATOMIC_OVERVIEW_ANIM_THRESHOLD;
- boolean passedThreshold = progress >= threshold;
+ boolean passedThreshold = progress >= ATOMIC_OVERVIEW_ANIM_THRESHOLD;
if (passedThreshold != mPassedOverviewAtomicThreshold) {
LauncherState atomicFromState = passedThreshold ? fromState: toState;
LauncherState atomicToState = passedThreshold ? toState : fromState;
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 098d90d..61bd30a 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -41,7 +41,6 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.folder.Folder;
@@ -59,6 +58,7 @@
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.views.FloatingIconView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAppWidgetHostView;
import com.android.launcher3.widget.WidgetAddFlowHandler;
import com.android.launcher3.widget.WidgetManagerHelper;
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index f05f15e..8a64f3d 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -147,13 +147,6 @@
}
@Override
- public void setPrimaryAndResetSecondaryTranslate(
- View view, float translation, float defaultTranslationX, float defaultTranslationY) {
- view.setTranslationX(defaultTranslationX);
- view.setTranslationY(translation);
- }
-
- @Override
public int getPrimaryScroll(View view) {
return view.getScrollY();
}
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index b9acfa3..e1cec87 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -66,8 +66,6 @@
int getSecondaryDimension(View view);
FloatProperty<View> getPrimaryViewTranslate();
FloatProperty<View> getSecondaryViewTranslate();
- void setPrimaryAndResetSecondaryTranslate(
- View view, float translation, float defaultTranslationX, float defaultTranslationY);
int getPrimaryScroll(View view);
float getPrimaryScale(View view);
int getChildStart(View view);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 3663b5f..bcaf5f4 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -143,13 +143,6 @@
}
@Override
- public void setPrimaryAndResetSecondaryTranslate(
- View view, float translation, float defaultTranslationX, float defaultTranslationY) {
- view.setTranslationX(translation);
- view.setTranslationY(defaultTranslationY);
- }
-
- @Override
public int getPrimaryScroll(View view) {
return view.getScrollX();
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
similarity index 96%
rename from src/com/android/launcher3/LauncherAppWidgetHost.java
rename to src/com/android/launcher3/widget/LauncherAppWidgetHost.java
index fea26df..d745754 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.widget;
import static android.app.Activity.RESULT_CANCELED;
@@ -29,12 +29,13 @@
import android.util.SparseArray;
import android.widget.Toast;
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.widget.DeferredAppWidgetHostView;
-import com.android.launcher3.widget.LauncherAppWidgetHostView;
-import com.android.launcher3.widget.PendingAppWidgetHostView;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.ArrayList;
@@ -199,7 +200,7 @@
}
}
- void addPendingView(int appWidgetId, PendingAppWidgetHostView view) {
+ public void addPendingView(int appWidgetId, PendingAppWidgetHostView view) {
mPendingViews.put(appWidgetId, view);
}
@@ -247,7 +248,7 @@
super.onProviderChanged(appWidgetId, info);
// The super method updates the dimensions of the providerInfo. Update the
// launcher spans accordingly.
- info.initSpans(mContext);
+ info.initSpans(mContext, LauncherAppState.getIDP(mContext));
}
/**
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 41098f9..54e51b2 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -37,7 +37,6 @@
import com.android.launcher3.CheckLongPressHelper;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
similarity index 86%
rename from src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
rename to src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index 618b5de..ce97d2e 100644
--- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -1,4 +1,4 @@
-package com.android.launcher3;
+package com.android.launcher3.widget;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
@@ -11,6 +11,9 @@
import android.os.Parcel;
import android.os.UserHandle;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -48,7 +51,7 @@
launcherInfo = new LauncherAppWidgetProviderInfo(p);
p.recycle();
}
- launcherInfo.initSpans(context);
+ launcherInfo.initSpans(context, LauncherAppState.getIDP(context));
return launcherInfo;
}
@@ -58,9 +61,7 @@
super(in);
}
- public void initSpans(Context context) {
- InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
-
+ public void initSpans(Context context, InvariantDeviceProfile idp) {
Point landCellSize = idp.landscapeProfile.getCellSize();
Point portCellSize = idp.portraitProfile.getCellSize();
@@ -71,8 +72,12 @@
// We want to account for the extra amount of padding that we are adding to the widget
// to ensure that it gets the full amount of space that it has requested.
- Rect widgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(
- context, provider, null);
+ // If grids supports insetting widgets, we do not account for widget padding.
+ Rect widgetPadding = new Rect();
+ if (!idp.landscapeProfile.shouldInsetWidgets()
+ || !idp.portraitProfile.shouldInsetWidgets()) {
+ AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding);
+ }
spanX = Math.max(1, (int) Math.ceil(
(minWidth + widgetPadding.left + widgetPadding.right) / smallestCellWidth));
spanY = Math.max(1, (int) Math.ceil(
diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
index ed42bc4..6163b51 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -17,6 +17,7 @@
package com.android.launcher3.widget;
import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -25,8 +26,11 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Reorderable;
import com.android.launcher3.dragndrop.DraggableView;
+import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
@@ -50,11 +54,16 @@
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
private float mScaleForReorderBounce = 1f;
+ private final Rect mTempRect = new Rect();
+
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mChildrenFocused;
+ protected final BaseActivity mActivity;
+
public NavigableAppWidgetHostView(Context context) {
super(context);
+ mActivity = ActivityContext.lookupContext(context);
}
@Override
@@ -222,6 +231,25 @@
int width = (int) (getMeasuredWidth() * mScaleToFit);
int height = (int) (getMeasuredHeight() * mScaleToFit);
- bounds.set(0, 0 , width, height);
+ getWidgetInset(mActivity.getDeviceProfile(), mTempRect);
+ bounds.set(mTempRect.left, mTempRect.top, width - mTempRect.right,
+ height - mTempRect.bottom);
+ }
+
+ /**
+ * Widgets have padding added by the system. We may choose to inset this padding if the grid
+ * supports it.
+ */
+ public void getWidgetInset(DeviceProfile grid, Rect out) {
+ if (!grid.shouldInsetWidgets()) {
+ out.setEmpty();
+ return;
+ }
+ AppWidgetProviderInfo info = getAppWidgetInfo();
+ if (info == null) {
+ out.set(grid.inv.defaultWidgetPadding);
+ } else {
+ AppWidgetHostView.getDefaultPaddingForWidget(getContext(), info.provider, out);
+ }
}
}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index bef9a08..ee0b84e 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -20,7 +20,6 @@
import android.appwidget.AppWidgetHostView;
import android.os.Bundle;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PendingAddItemInfo;
diff --git a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
index ebc2a25..1ac5a33 100644
--- a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
+++ b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java
@@ -21,7 +21,6 @@
import android.os.Parcelable;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.PendingRequestArgs;
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index c6593f8..8c315fd 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -16,6 +16,8 @@
package com.android.launcher3.widget;
+import static com.android.launcher3.Utilities.ATLEAST_S;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.os.CancellationSignal;
@@ -67,6 +69,7 @@
private WidgetImageView mWidgetImage;
private TextView mWidgetName;
private TextView mWidgetDims;
+ private TextView mWidgetDescription;
protected WidgetItem mItem;
@@ -114,9 +117,10 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mWidgetImage = (WidgetImageView) findViewById(R.id.widget_preview);
- mWidgetName = ((TextView) findViewById(R.id.widget_name));
- mWidgetDims = ((TextView) findViewById(R.id.widget_dims));
+ mWidgetImage = findViewById(R.id.widget_preview);
+ mWidgetName = findViewById(R.id.widget_name);
+ mWidgetDims = findViewById(R.id.widget_dims);
+ mWidgetDescription = findViewById(R.id.widget_description);
}
/**
@@ -130,6 +134,8 @@
mWidgetImage.setBitmap(null, null);
mWidgetName.setText(null);
mWidgetDims.setText(null);
+ mWidgetDescription.setText(null);
+ mWidgetDescription.setVisibility(GONE);
mPreviewWidth = mPreviewHeight = mPresetPreviewSize;
if (mActiveRequest != null) {
@@ -145,8 +151,17 @@
mItem.spanX, mItem.spanY));
mWidgetDims.setContentDescription(getContext().getString(
R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
- mWidgetPreviewLoader = loader;
+ if (ATLEAST_S && mItem.widgetInfo != null) {
+ CharSequence description = mItem.widgetInfo.loadDescription(getContext());
+ if (description != null && description.length() > 0) {
+ mWidgetDescription.setText(description);
+ mWidgetDescription.setVisibility(VISIBLE);
+ } else {
+ mWidgetDescription.setVisibility(GONE);
+ }
+ }
+ mWidgetPreviewLoader = loader;
if (item.activityInfo != null) {
setTag(new PendingAddShortcutInfo(item.activityInfo));
} else {
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 2438bdf..31cbff6 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -13,7 +13,6 @@
import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.DropTarget;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index c0c5c48..15fa844 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -27,18 +27,14 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -122,15 +118,6 @@
appWidgetId).getBoolean(WIDGET_OPTION_RESTORE_COMPLETED);
}
- public static Map<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap(Context context) {
- if (WidgetsModel.GO_DISABLE_WIDGETS) {
- return Collections.emptyMap();
- }
- return allWidgetsSteam(context).collect(
- Collectors.toMap(info -> new ComponentKey(info.provider, info.getProfile()),
- Function.identity()));
- }
-
private static Stream<AppWidgetProviderInfo> allWidgetsSteam(Context context) {
AppWidgetManager awm = context.getSystemService(AppWidgetManager.class);
return Stream.concat(
diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
index 1086987..8b3bbce 100644
--- a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
@@ -22,8 +22,9 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Utilities;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
/**
* Custom app widget provider info that can be used as a widget, but provide extra functionality
@@ -57,7 +58,7 @@
}
@Override
- public void initSpans(Context context) { }
+ public void initSpans(Context context, InvariantDeviceProfile idp) { }
@Override
public String getLabel(PackageManager packageManager) {
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
index 0b66ec0..329a444 100644
--- a/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetManager.java
@@ -16,7 +16,7 @@
package com.android.launcher3.widget.custom;
-import static com.android.launcher3.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
+import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
@@ -29,12 +29,12 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.systemui.plugins.CustomWidgetPlugin;
import com.android.systemui.plugins.PluginListener;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 3a186c5..91b79f9 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -45,13 +45,13 @@
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.TopRoundedCornerView;
import com.android.launcher3.widget.BaseWidgetSheet;
+import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.workprofile.PersonalWorkPagedView;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index a7e3472..a8c7c48 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -17,7 +17,6 @@
import com.android.launcher3.AppFilter;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -27,6 +26,7 @@
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index b3c1240..0edfbed 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -151,23 +151,30 @@
}
public static String dumpHprofData() {
- if (sDumpWasGenerated) return "dump has already been generated by another test";
- try {
- final String fileName = getInstrumentation().getTargetContext().getFilesDir().getPath()
- + "/ActivityLeakHeapDump.hprof";
- if (TestHelpers.isInLauncherProcess()) {
- Debug.dumpHprofData(fileName);
- } else {
- final UiDevice device = UiDevice.getInstance(getInstrumentation());
- device.executeShellCommand(
- "am dumpheap " + device.getLauncherPackageName() + " " + fileName);
+ String result;
+ if (sDumpWasGenerated) {
+ result = "dump has already been generated by another test";
+ } else {
+ try {
+ final String fileName =
+ getInstrumentation().getTargetContext().getFilesDir().getPath()
+ + "/ActivityLeakHeapDump.hprof";
+ if (TestHelpers.isInLauncherProcess()) {
+ Debug.dumpHprofData(fileName);
+ } else {
+ final UiDevice device = UiDevice.getInstance(getInstrumentation());
+ device.executeShellCommand(
+ "am dumpheap " + device.getLauncherPackageName() + " " + fileName);
+ }
+ sDumpWasGenerated = true;
+ result = "memory dump filename: " + fileName;
+ } catch (Throwable e) {
+ Log.e(TAG, "dumpHprofData failed", e);
+ result = "failed to save memory dump";
}
- sDumpWasGenerated = true;
- return "memory dump filename: " + fileName;
- } catch (Throwable e) {
- Log.e(TAG, "dumpHprofData failed", e);
- return "failed to save memory dump";
}
+ return result
+ + ". Full list of activities: " + ACTIVITY_LEAK_TRACKER.getActivitiesList();
}
protected AbstractLauncherUiTest() {
diff --git a/tests/src/com/android/launcher3/ui/ActivityLeakTracker.java b/tests/src/com/android/launcher3/ui/ActivityLeakTracker.java
index dd216c7..2db7472 100644
--- a/tests/src/com/android/launcher3/ui/ActivityLeakTracker.java
+++ b/tests/src/com/android/launcher3/ui/ActivityLeakTracker.java
@@ -25,6 +25,7 @@
import com.android.launcher3.tapl.TestHelpers;
import java.util.WeakHashMap;
+import java.util.stream.Collectors;
public class ActivityLeakTracker implements Application.ActivityLifecycleCallbacks {
private final WeakHashMap<Activity, Boolean> mActivities = new WeakHashMap<>();
@@ -81,4 +82,9 @@
return mActivities.size() <= 2;
}
+
+ public String getActivitiesList() {
+ return mActivities.keySet().stream().map(a -> a.getClass().getSimpleName())
+ .collect(Collectors.joining(","));
+ }
}
diff --git a/tests/src/com/android/launcher3/ui/TestViewHelpers.java b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
index eceff34..083f580 100644
--- a/tests/src/com/android/launcher3/ui/TestViewHelpers.java
+++ b/tests/src/com/android/launcher3/ui/TestViewHelpers.java
@@ -24,9 +24,9 @@
import android.view.View;
import android.view.ViewGroup;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.testcomponent.AppWidgetNoConfig;
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import java.util.concurrent.Callable;
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 737f891..b421b0e 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -28,7 +28,6 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Workspace;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -39,6 +38,7 @@
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
import com.android.launcher3.util.rule.ShellCommandRule;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import org.junit.Before;
import org.junit.Rule;
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index f146db5..714b11b 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -23,12 +23,12 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.tapl.Widget;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import org.junit.Rule;
import org.junit.Test;
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index fa495f5..9c6c317 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -37,7 +37,6 @@
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -47,6 +46,7 @@
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestViewHelpers;
import com.android.launcher3.util.rule.ShellCommandRule;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import org.junit.After;
diff --git a/tests/src_common/com/android/launcher3/common/WidgetUtils.java b/tests/src_common/com/android/launcher3/common/WidgetUtils.java
index c0913bf..ffad93f 100644
--- a/tests/src_common/com/android/launcher3/common/WidgetUtils.java
+++ b/tests/src_common/com/android/launcher3/common/WidgetUtils.java
@@ -23,12 +23,12 @@
import android.content.Context;
import android.os.Bundle;
-import com.android.launcher3.LauncherAppWidgetHost;
-import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.widget.LauncherAppWidgetHost;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetManagerHelper;