Merge "fixing rare NPE" into tm-qpr-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index c638ba9..02460e4 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -132,6 +132,8 @@
// Next value 44
enum Attribute {
+ option allow_alias = true;
+
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
BACKUP_RESTORE = 2; // icon layout restored from backup
@@ -166,7 +168,8 @@
ALL_APPS_SEARCH_RESULT_SLICE = 19;
ALL_APPS_SEARCH_RESULT_WIDGETS = 20;
ALL_APPS_SEARCH_RESULT_PLAY = 21;
- ALL_APPS_SEARCH_RESULT_SUGGEST = 22;
+ ALL_APPS_SEARCH_RESULT_FALLBACK = 22;
+ ALL_APPS_SEARCH_RESULT_SUGGEST = 22 [deprecated = true];
ALL_APPS_SEARCH_RESULT_ASSISTANT = 23;
ALL_APPS_SEARCH_RESULT_CHROMETAB = 24;
ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25;
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
index f08cabe..7ea92b5 100644
--- a/quickstep/res/layout/activity_allset.xml
+++ b/quickstep/res/layout/activity_allset.xml
@@ -38,6 +38,7 @@
app:lottie_loop="true" />
<androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/text_content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/allset_page_margin_horizontal"
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index 1630d0f..9982162 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -52,7 +52,7 @@
private final float mUnstashArea;
private final float mScreenWidth;
- private final int mTaskbarNavThresholdY;
+ private final int mTaskbarNavThreshold;
private final boolean mIsTaskbarAllAppsOpen;
private boolean mHasPassedTaskbarNavThreshold;
@@ -73,9 +73,7 @@
Resources res = context.getResources();
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
- int taskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
- int screenHeight = taskbarActivityContext.getDeviceProfile().heightPx;
- mTaskbarNavThresholdY = screenHeight - taskbarNavThreshold;
+ mTaskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
mIsTaskbarAllAppsOpen =
mTaskbarActivityContext != null && mTaskbarActivityContext.isTaskbarAllAppsOpen();
@@ -157,7 +155,7 @@
if (mIsTransientTaskbar) {
float dY = mLastPos.y - mDownPos.y;
boolean passedTaskbarNavThreshold = dY < 0
- && mLastPos.y < mTaskbarNavThresholdY;
+ && Math.abs(dY) >= mTaskbarNavThreshold;
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
@@ -165,7 +163,7 @@
}
if (dY < 0) {
- dY = -OverScroll.dampedScroll(-dY, mTaskbarNavThresholdY);
+ dY = -OverScroll.dampedScroll(-dY, mTaskbarNavThreshold);
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionMove(dY);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 0389d07..79971de 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -88,6 +88,10 @@
private static final float ANIMATION_PAUSE_ALPHA_THRESHOLD = 0.1f;
+ private final Rect mTempSettingsBounds = new Rect();
+ private final Rect mTempInclusionBounds = new Rect();
+ private final Rect mTempExclusionBounds = new Rect();
+
private TISBindHelper mTISBindHelper;
private TISBinder mBinder;
@@ -131,9 +135,9 @@
!TextUtils.isEmpty(suwDeviceName)
? suwDeviceName : getString(R.string.default_device_name)));
- TextView tv = findViewById(R.id.navigation_settings);
- tv.setTextColor(accentColor);
- tv.setOnClickListener(v -> {
+ TextView settings = findViewById(R.id.navigation_settings);
+ settings.setTextColor(accentColor);
+ settings.setOnClickListener(v -> {
try {
startActivityForResult(
Intent.parseUri(URI_SYSTEM_NAVIGATION_SETTING, 0), 0);
@@ -142,12 +146,41 @@
}
});
- TextView hintTextView = findViewById(R.id.hint);
+ TextView hint = findViewById(R.id.hint);
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
if (!dp.isGestureMode) {
- hintTextView.setText(R.string.allset_button_hint);
+ hint.setText(R.string.allset_button_hint);
}
- hintTextView.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+ hint.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+
+ View textContent = findViewById(R.id.text_content_view);
+ textContent.addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ mTempSettingsBounds.set(
+ settings.getLeft(),
+ settings.getTop(),
+ settings.getRight(),
+ settings.getBottom());
+ mTempInclusionBounds.set(
+ 0,
+ // Do not allow overlapping with the subtitle text
+ subtitle.getBottom(),
+ textContent.getWidth(),
+ textContent.getHeight());
+ mTempExclusionBounds.set(
+ hint.getLeft(),
+ hint.getTop(),
+ hint.getRight(),
+ hint.getBottom());
+
+ Utilities.translateOverlappingView(
+ settings,
+ mTempSettingsBounds,
+ mTempInclusionBounds,
+ mTempExclusionBounds,
+ Utilities.TRANSLATE_UP);
+ });
+
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
mVibrator = getSystemService(Vibrator.class);
diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
index bd0ce34..b508484 100644
--- a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
+++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.graphics.Insets;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -34,6 +35,10 @@
/** Root layout that TutorialFragment uses to intercept motion events. */
public class RootSandboxLayout extends RelativeLayout {
+ private final Rect mTempStepIndicatorBounds = new Rect();
+ private final Rect mTempInclusionBounds = new Rect();
+ private final Rect mTempExclusionBounds = new Rect();
+
private View mFeedbackView;
private View mTutorialStepView;
private View mSkipButton;
@@ -98,18 +103,23 @@
private void updateTutorialStepViewTranslation(
@NonNull View anchorView, boolean translateToRight) {
- mTutorialStepView.setTranslationX(translateToRight
- ? Math.min(
- // Translate to the right if the views are overlapping on large fonts and
- // display sizes.
- Math.max(0, anchorView.getRight() - mTutorialStepView.getLeft()),
- // Do not translate beyond the bounds of the container view.
- mFeedbackView.getWidth() - mTutorialStepView.getRight())
- : Math.max(
- // Translate to the left if the views are overlapping on large fonts and
- // display sizes.
- Math.min(0, anchorView.getLeft() - mTutorialStepView.getRight()),
- // Do not translate beyond the bounds of the container view.
- -mTutorialStepView.getLeft()));
+ mTempStepIndicatorBounds.set(
+ mTutorialStepView.getLeft(),
+ mTutorialStepView.getTop(),
+ mTutorialStepView.getRight(),
+ mTutorialStepView.getBottom());
+ mTempInclusionBounds.set(0, 0, mFeedbackView.getWidth(), mFeedbackView.getHeight());
+ mTempExclusionBounds.set(
+ anchorView.getLeft(),
+ anchorView.getTop(),
+ anchorView.getRight(),
+ anchorView.getBottom());
+
+ Utilities.translateOverlappingView(
+ mTutorialStepView,
+ mTempStepIndicatorBounds,
+ mTempInclusionBounds,
+ mTempExclusionBounds,
+ translateToRight ? Utilities.TRANSLATE_RIGHT : Utilities.TRANSLATE_LEFT);
}
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 59327dc..0fbaecb 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -65,6 +65,7 @@
import android.view.animation.Interpolator;
import androidx.annotation.ChecksSdkIntAtLeast;
+import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
@@ -136,6 +137,14 @@
@Deprecated
public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE;
+ public static final int TRANSLATE_UP = 0;
+ public static final int TRANSLATE_DOWN = 1;
+ public static final int TRANSLATE_LEFT = 2;
+ public static final int TRANSLATE_RIGHT = 3;
+
+ @IntDef({TRANSLATE_UP, TRANSLATE_DOWN, TRANSLATE_LEFT, TRANSLATE_RIGHT})
+ public @interface AdjustmentDirection{}
+
/**
* Returns true if theme is dark.
*/
@@ -731,4 +740,63 @@
matrixValues[Matrix.MTRANS_X], matrixValues[Matrix.MTRANS_Y]
));
}
+
+ /**
+ * Translates the {@code targetView} so that it overlaps with {@code exclusionBounds} as little
+ * as possible, while remaining within {@code inclusionBounds}.
+ * <p>
+ * {@code inclusionBounds} will always take precedence over {@code exclusionBounds}, so if
+ * {@code targetView} needs to be translated outside of {@code inclusionBounds} to fully fix an
+ * overlap with {@code exclusionBounds}, then {@code targetView} will only be translated up to
+ * the border of {@code inclusionBounds}.
+ * <p>
+ * Note: {@code targetViewBounds}, {@code inclusionBounds} and {@code exclusionBounds} must all
+ * be in relation to the same reference point on screen.
+ * <p>
+ * @param targetView the view being translated
+ * @param targetViewBounds the bounds of the {@code targetView}
+ * @param inclusionBounds the bounds the {@code targetView} absolutely must stay within
+ * @param exclusionBounds the bounds to try to move the {@code targetView} away from
+ * @param adjustmentDirection the translation direction that should be attempted to fix an
+ * overlap
+ */
+ public static void translateOverlappingView(
+ @NonNull View targetView,
+ @NonNull Rect targetViewBounds,
+ @NonNull Rect inclusionBounds,
+ @NonNull Rect exclusionBounds,
+ @AdjustmentDirection int adjustmentDirection) {
+ switch (adjustmentDirection) {
+ case TRANSLATE_RIGHT:
+ targetView.setTranslationX(Math.min(
+ // Translate to the right if the view is overlapping on the left.
+ Math.max(0, exclusionBounds.right - targetViewBounds.left),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.right - targetViewBounds.right));
+ break;
+ case TRANSLATE_LEFT:
+ targetView.setTranslationX(Math.max(
+ // Translate to the left if the view is overlapping on the right.
+ Math.min(0, exclusionBounds.left - targetViewBounds.right),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.left - targetViewBounds.left));
+ break;
+ case TRANSLATE_DOWN:
+ targetView.setTranslationY(Math.min(
+ // Translate downwards if the view is overlapping on the top.
+ Math.max(0, exclusionBounds.bottom - targetViewBounds.top),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.bottom - targetViewBounds.bottom));
+ break;
+ case TRANSLATE_UP:
+ targetView.setTranslationY(Math.max(
+ // Translate upwards if the view is overlapping on the bottom.
+ Math.min(0, exclusionBounds.top - targetViewBounds.bottom),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.top - targetViewBounds.top));
+ break;
+ default:
+ // No-Op
+ }
+ }
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 68ece03..4f94c92 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -33,6 +33,7 @@
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.core.view.ViewCompat;
import com.android.launcher3.DeviceProfile;
@@ -61,7 +62,7 @@
implements OnClickListener, OnLongClickListener, DragSource,
PopupDataProvider.PopupDataChangeListener, Insettable {
/** The default number of cells that can fit horizontally in a widget sheet. */
- protected static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
+ public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
protected static final String KEY_WIDGETS_EDUCATION_TIP_SEEN =
"launcher.widgets_education_tip_seen";
@@ -70,15 +71,18 @@
/* Touch handling related member variables. */
private Toast mWidgetInstructionToast;
- private int mContentHorizontalMarginInPx;
+ @Px protected int mContentHorizontalMargin;
+ @Px protected int mWidgetCellHorizontalPadding;
protected int mNavBarScrimHeight;
private final Paint mNavBarScrimPaint;
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mContentHorizontalMarginInPx = getResources().getDimensionPixelSize(
+ mContentHorizontalMargin = getResources().getDimensionPixelSize(
R.dimen.widget_list_horizontal_margin);
+ mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
+ R.dimen.widget_cell_horizontal_padding);
mNavBarScrimPaint = new Paint();
mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
}
@@ -138,11 +142,11 @@
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
- int contentHorizontalMarginInPx = getResources().getDimensionPixelSize(
+ @Px int contentHorizontalMargin = getResources().getDimensionPixelSize(
R.dimen.widget_list_horizontal_margin);
- if (contentHorizontalMarginInPx != mContentHorizontalMarginInPx) {
- onContentHorizontalMarginChanged(contentHorizontalMarginInPx);
- mContentHorizontalMarginInPx = contentHorizontalMarginInPx;
+ if (contentHorizontalMargin != mContentHorizontalMargin) {
+ onContentHorizontalMarginChanged(contentHorizontalMargin);
+ mContentHorizontalMargin = contentHorizontalMargin;
}
}
@@ -198,19 +202,6 @@
MeasureSpec.getSize(heightMeasureSpec));
}
- /** Returns the number of cells that can fit horizontally in a given {@code content}. */
- protected int computeMaxHorizontalSpans(View content, int contentHorizontalPaddingPx) {
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- int availableWidth = content.getMeasuredWidth()
- - contentHorizontalPaddingPx
- - (2 * mContentHorizontalMarginInPx);
- Point cellSize = deviceProfile.getCellSize();
- if (cellSize.x > 0) {
- return availableWidth / cellSize.x;
- }
- return DEFAULT_MAX_HORIZONTAL_SPANS;
- }
-
private boolean beginDraggingWidget(WidgetCell v) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_DROP_TARGET, "2");
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 4099302..06c622d 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -36,6 +36,8 @@
import android.widget.TableRow;
import android.widget.TextView;
+import androidx.annotation.Px;
+
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.WidgetItem;
@@ -69,8 +71,7 @@
private static final long EDUCATION_TIP_DELAY_MS = 300;
private ItemInfo mOriginalItemInfo;
- private int mMaxHorizontalSpan = DEFAULT_MAX_HORIZONTAL_SPANS;
- private final int mWidgetCellHorizontalPadding;
+ @Px private int mMaxHorizontalSpan;
private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
new OnLayoutChangeListener() {
@@ -111,8 +112,6 @@
if (!hasSeenEducationTip()) {
addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
}
- mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
- R.dimen.widget_cell_horizontal_padding);
setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
}
@@ -134,7 +133,7 @@
private boolean updateMaxSpansPerRow() {
if (getMeasuredWidth() == 0) return false;
- int maxHorizontalSpan = computeMaxHorizontalSpans(mContent, mWidgetCellHorizontalPadding);
+ @Px int maxHorizontalSpan = mContent.getMeasuredWidth() - (2 * mContentHorizontalMargin);
if (mMaxHorizontalSpan != maxHorizontalSpan) {
// Ensure the table layout is showing widgets in the right column after measure.
mMaxHorizontalSpan = maxHorizontalSpan;
@@ -184,7 +183,9 @@
TableLayout widgetsTable = findViewById(R.id.widgets_table);
widgetsTable.removeAllViews();
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(widgets, mMaxHorizontalSpan)
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgets, mActivityContext,
+ mActivityContext.getDeviceProfile(), mMaxHorizontalSpan,
+ mWidgetCellHorizontalPadding)
.forEach(row -> {
TableRow tableRow = new TableRow(getContext());
tableRow.setGravity(Gravity.TOP);
diff --git a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
index 626e0b9..d709196 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget.model;
+import androidx.annotation.Px;
+
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
@@ -26,7 +28,7 @@
*/
public final class WidgetsListContentEntry extends WidgetsListBaseEntry {
- private final int mMaxSpanSizeInCells;
+ @Px private final int mMaxSpanSize;
/**
* Constructor for {@link WidgetsListContentEntry}.
@@ -37,7 +39,7 @@
*/
public WidgetsListContentEntry(PackageItemInfo pkgItem, String titleSectionName,
List<WidgetItem> items) {
- this(pkgItem, titleSectionName, items, /* maxSpanSizeInCells= */ 0);
+ this(pkgItem, titleSectionName, items, /* maxSpanSize= */ 0);
}
/**
@@ -46,43 +48,43 @@
* @param pkgItem package info associated with the entry
* @param titleSectionName title section name associated with the entry.
* @param items list of widgets for the package.
- * @param maxSpanSizeInCells the max horizontal span in cells that is allowed for grouping more
+ * @param maxSpanSize the max horizontal span in pixels that is allowed for grouping more
* than one widgets in a table row.
*/
public WidgetsListContentEntry(PackageItemInfo pkgItem, String titleSectionName,
- List<WidgetItem> items, int maxSpanSizeInCells) {
+ List<WidgetItem> items, @Px int maxSpanSize) {
super(pkgItem, titleSectionName, items);
- mMaxSpanSizeInCells = maxSpanSizeInCells;
+ mMaxSpanSize = maxSpanSize;
}
@Override
public String toString() {
- return "Content:" + mPkgItem.packageName + ":" + mWidgets.size() + " maxSpanSizeInCells: "
- + mMaxSpanSizeInCells;
+ return "Content:" + mPkgItem.packageName + ":" + mWidgets.size() + " maxSpanSize: "
+ + mMaxSpanSize;
}
/**
- * Returns a copy of this {@link WidgetsListContentEntry} with updated
- * {@param maxSpanSizeInCells}.
+ * Returns a copy of this {@link WidgetsListContentEntry} with updated {@code maxSpanSize}.
*
- * @param maxSpanSizeInCells the maximum horizontal span in cells that is allowed for grouping
+ * @param maxSpanSize the maximum horizontal span in pixels that is allowed for grouping
* more than one widgets in a table row.
*/
- public WidgetsListContentEntry withMaxSpanSize(int maxSpanSizeInCells) {
- if (mMaxSpanSizeInCells == maxSpanSizeInCells) return this;
+ public WidgetsListContentEntry withMaxSpanSize(@Px int maxSpanSize) {
+ if (mMaxSpanSize == maxSpanSize) return this;
return new WidgetsListContentEntry(
mPkgItem,
mTitleSectionName,
mWidgets,
- /* maxSpanSizeInCells= */ maxSpanSizeInCells);
+ /* maxSpanSize= */ maxSpanSize);
}
/**
- * Returns the max horizontal span size in cells that is allowed for grouping more than one
+ * Returns the max horizontal span size in pixels that is allowed for grouping more than one
* widget in a table row.
*/
- public int getMaxSpanSizeInCells() {
- return mMaxSpanSizeInCells;
+ @Px
+ public int getMaxSpanSize() {
+ return mMaxSpanSize;
}
@Override
@@ -91,6 +93,6 @@
WidgetsListContentEntry otherEntry = (WidgetsListContentEntry) obj;
return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
&& mTitleSectionName.equals(otherEntry.mTitleSectionName)
- && mMaxSpanSizeInCells == otherEntry.mMaxSpanSizeInCells;
+ && mMaxSpanSize == otherEntry.mMaxSpanSize;
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index f4d6749..d5c4315 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -53,6 +53,7 @@
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
@@ -181,14 +182,13 @@
}
};
- private final int mTabsHeight;
- private final int mWidgetSheetContentHorizontalPadding;
+ @Px private final int mTabsHeight;
@Nullable private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
@Nullable private PersonalWorkPagedView mViewPager;
private boolean mIsInSearchMode;
private boolean mIsNoWidgetsViewNeeded;
- private int mMaxSpansPerRow = DEFAULT_MAX_HORIZONTAL_SPANS;
+ @Px private int mMaxSpanPerRow;
private TextView mNoWidgetsView;
private StickyHeaderLayout mSearchScrollView;
@@ -224,8 +224,6 @@
mTabsHeight = mHasWorkProfile
? resources.getDimensionPixelSize(R.dimen.all_apps_header_pill_height)
: 0;
- mWidgetSheetContentHorizontalPadding = 2 * resources.getDimensionPixelSize(
- R.dimen.widget_cell_horizontal_padding);
mUserManagerState.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
@@ -337,7 +335,7 @@
: mSearchScrollView.findViewById(R.id.title);
mRightPane = mIsTwoPane ? mContent.findViewById(R.id.right_pane) : null;
mWidgetsListTableViewHolderBinder =
- new WidgetsListTableViewHolderBinder(layoutInflater, this, this);
+ new WidgetsListTableViewHolderBinder(mActivityContext, layoutInflater, this, this);
onRecommendedWidgetsBound();
onWidgetsBound();
@@ -536,22 +534,20 @@
View content = mHasWorkProfile
? mViewPager
: mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView;
-
if (mIsTwoPane && mRightPane != null) {
content = mRightPane;
}
- int maxHorizontalSpans = computeMaxHorizontalSpans(content,
- mWidgetSheetContentHorizontalPadding);
- if (mMaxSpansPerRow != maxHorizontalSpans) {
- mMaxSpansPerRow = maxHorizontalSpans;
- mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
- mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
+ @Px int maxHorizontalSpan = content.getMeasuredWidth() - (2 * mContentHorizontalMargin);
+ if (mMaxSpanPerRow != maxHorizontalSpan) {
+ mMaxSpanPerRow = maxHorizontalSpan;
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
+ mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
if (mHasWorkProfile) {
- mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
+ mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
}
onRecommendedWidgetsBound();
return true;
@@ -700,8 +696,12 @@
- noWidgetsViewHeight) * RECOMMENDATION_TABLE_HEIGHT_RATIO;
List<ArrayList<WidgetItem>> recommendedWidgetsInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
- recommendedWidgets, mMaxSpansPerRow);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering(
+ recommendedWidgets,
+ mActivityContext,
+ mActivityContext.getDeviceProfile(),
+ mMaxSpanPerRow,
+ mWidgetCellHorizontalPadding);
mRecommendedWidgetsTable.setRecommendedWidgets(
recommendedWidgetsInTable, maxTableHeight);
} else {
@@ -1051,7 +1051,7 @@
if (mAdapterType == PRIMARY || mAdapterType == WORK) {
mWidgetsRecyclerView.addOnAttachStateChangeListener(mBindScrollbarInSearchMode);
}
- mWidgetsListAdapter.setMaxHorizontalSpansPerRow(mMaxSpansPerRow);
+ mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(mMaxSpanPerRow);
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index c28402e..c89eea8 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_DEFAULT;
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_FIRST;
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_LAST;
+import static com.android.launcher3.widget.BaseWidgetSheet.DEFAULT_MAX_HORIZONTAL_SPANS;
import android.content.Context;
import android.os.Process;
@@ -32,6 +33,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.DiffUtil.DiffResult;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -49,6 +51,7 @@
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
+import com.android.launcher3.widget.util.WidgetSizes;
import java.util.ArrayList;
import java.util.Arrays;
@@ -99,7 +102,7 @@
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
@Nullable private RecyclerView mRecyclerView;
@Nullable private PackageUserKey mPendingClickHeader;
- private int mMaxSpanSize = 4;
+ @Px private int mMaxHorizontalSpan;
public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
IntSupplier emptySpaceHeightProvider, OnClickListener iconClickListener,
@@ -107,11 +110,14 @@
WidgetsFullSheet.HeaderChangeListener headerChangeListener) {
mHeaderChangeListener = headerChangeListener;
mContext = context;
+ mMaxHorizontalSpan = WidgetSizes.getWidgetSizePx(
+ ActivityContext.lookupContext(context).getDeviceProfile(),
+ DEFAULT_MAX_HORIZONTAL_SPANS, 1).getWidth();
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_LIST,
new WidgetsListTableViewHolderBinder(
- layoutInflater, iconClickListener, iconLongClickListener));
+ mContext, layoutInflater, iconClickListener, iconLongClickListener));
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_HEADER,
new WidgetsListHeaderViewHolderBinder(
@@ -199,7 +205,8 @@
} else if (entry instanceof WidgetsListContentEntry) {
// Adjust the original content entries to accommodate for the current
// maxSpanSize.
- return ((WidgetsListContentEntry) entry).withMaxSpanSize(mMaxSpanSize);
+ return ((WidgetsListContentEntry) entry).withMaxSpanSize(
+ mMaxHorizontalSpan);
}
return entry;
})
@@ -407,11 +414,11 @@
}
/**
- * Sets the max horizontal span in cells that is allowed for grouping more than one widget in a
+ * Sets the max horizontal span in pixels that is allowed for grouping more than one widget in a
* table row.
*/
- public void setMaxHorizontalSpansPerRow(int maxHorizontalSpans) {
- mMaxSpanSize = maxHorizontalSpans;
+ public void setMaxHorizontalSpansPxPerRow(@Px int maxHorizontalSpan) {
+ mMaxHorizontalSpan = maxHorizontalSpan;
updateVisibleEntries();
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index 2e8f0ab..c7d2aa3 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.widget.picker;
+import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.util.Pair;
@@ -27,9 +28,13 @@
import android.widget.TableLayout;
import android.widget.TableRow;
+import androidx.annotation.NonNull;
+import androidx.annotation.Px;
+
import com.android.launcher3.R;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.recyclerview.ViewHolderBinder;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.util.WidgetsTableUtils;
@@ -47,13 +52,21 @@
private final LayoutInflater mLayoutInflater;
private final OnClickListener mIconClickListener;
+ private @NonNull final Context mContext;
+ private @NonNull final ActivityContext mActivityContext;
+ @Px private final int mCellPadding;
private final OnLongClickListener mIconLongClickListener;
public WidgetsListTableViewHolderBinder(
+ @NonNull Context context,
LayoutInflater layoutInflater,
OnClickListener iconClickListener,
OnLongClickListener iconLongClickListener) {
mLayoutInflater = layoutInflater;
+ mContext = context;
+ mActivityContext = ActivityContext.lookupContext(context);
+ mCellPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.widget_cell_horizontal_padding);
mIconClickListener = iconClickListener;
mIconLongClickListener = iconLongClickListener;
}
@@ -87,8 +100,11 @@
(position & POSITION_LAST) != 0));
List<ArrayList<WidgetItem>> widgetItemsTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- entry.mWidgets, entry.getMaxSpanSizeInCells());
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(entry.mWidgets,
+ mContext,
+ mActivityContext.getDeviceProfile(),
+ entry.getMaxSpanSize(),
+ mCellPadding);
recycleTableBeforeBinding(table, widgetItemsTable);
// Bind the widget items.
diff --git a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
index 72e27bf..74d3062 100644
--- a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
+++ b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
@@ -15,6 +15,11 @@
*/
package com.android.launcher3.widget.util;
+import android.content.Context;
+
+import androidx.annotation.Px;
+
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.model.WidgetItem;
import java.util.ArrayList;
@@ -49,34 +54,41 @@
* Groups {@code widgetItems} items into a 2D array which matches their appearance in a UI
* table. This takes liberty to rearrange widgets to make the table visually appealing.
*/
- public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithReordering(
- List<WidgetItem> widgetItems, final int maxSpansPerRow) {
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsUsingRowPxWithReordering(
+ List<WidgetItem> widgetItems, Context context, final DeviceProfile dp,
+ final @Px int rowPx, final @Px int cellPadding) {
List<WidgetItem> sortedWidgetItems = widgetItems.stream().sorted(WIDGET_SHORTCUT_COMPARATOR)
.collect(Collectors.toList());
- return groupWidgetItemsIntoTableWithoutReordering(sortedWidgetItems, maxSpansPerRow);
+ return groupWidgetItemsUsingRowPxWithoutReordering(sortedWidgetItems, context, dp, rowPx,
+ cellPadding);
}
/**
* Groups {@code widgetItems} into a 2D array which matches their appearance in a UI table while
- * maintaining their order.
+ * maintaining their order. This function is a variant of
+ * {@code groupWidgetItemsIntoTableWithoutReordering} in that this uses widget pixels for
+ * calculation.
*
* <p>Grouping:
* 1. Widgets and shortcuts never group together in the same row.
- * 2. The ordered widgets are grouped together in the same row until their total horizontal
- * spans exceed the {@code maxSpansPerRow} - 1.
- * 3. The order shortcuts are grouped together in the same row until their total horizontal
- * spans exceed the {@code maxSpansPerRow} - 1.
- * 4. If there is only one widget in a row, its width may exceed the {@code maxSpansPerRow}.
+ * 2. The ordered widgets are grouped together in the same row until their individual occupying
+ * pixels exceed the total allowed pixels for the cell.
+ * 3. The ordered shortcuts are grouped together in the same row until their individual
+ * occupying pixels exceed the total allowed pixels for the cell.
+ * 4. If there is only one widget in a row, its width may exceed the {@code rowPx}.
*
- * <p>Let's say the {@code maxSpansPerRow} is set to 6. Widgets can be grouped in the same row
- * if their total horizontal spans added don't exceed 5.
- * Example 1: Row 1: 2x2, 2x3, 1x1. Total horizontal spans is 5. This is okay.
- * Example 2: Row 1: 2x2, 4x3, 1x1. the total horizontal spans is 7. This is wrong. 4x3 and 1x1
- * should be moved to a new row.
- * Example 3: Row 1: 6x4. This is okay because this is the only item in the row.
+ * <p>Let's say the {@code rowPx} is set to 600 and we have 5 widgets. Widgets can be grouped
+ * in the same row if each of their individual occupying pixels does not exceed
+ * {@code rowPx} / 5 - 2 * {@code cellPadding}.
+ * Example 1: Row 1: 200x200, 200x300, 100x100. Average horizontal pixels is 200 and no widgets
+ * exceed that width. This is okay.
+ * Example 2: Row 1: 200x200, 400x300, 100x100. Average horizontal pixels is 200 and one widget
+ * exceed that width. This is not allowed.
+ * Example 3: Row 1: 700x400. This is okay because this is the only item in the row.
*/
- public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithoutReordering(
- List<WidgetItem> widgetItems, final int maxSpansPerRow) {
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsUsingRowPxWithoutReordering(
+ List<WidgetItem> widgetItems, Context context, final DeviceProfile dp,
+ final @Px int rowPx, final @Px int cellPadding) {
List<ArrayList<WidgetItem>> widgetItemsTable = new ArrayList<>();
ArrayList<WidgetItem> widgetItemsAtRow = null;
@@ -86,23 +98,28 @@
widgetItemsTable.add(widgetItemsAtRow);
}
int numOfWidgetItems = widgetItemsAtRow.size();
- int totalHorizontalSpan = widgetItemsAtRow.stream().map(item -> item.spanX)
- .reduce(/* default= */ 0, Integer::sum);
- int totalHorizontalSpanAfterAddingWidget = widgetItem.spanX + totalHorizontalSpan;
+ @Px int individualSpan = (rowPx / (numOfWidgetItems + 1)) - (2 * cellPadding);
if (numOfWidgetItems == 0) {
widgetItemsAtRow.add(widgetItem);
} else if (
- // The max spans per row is reduced by 1 to ensure we don't pack too many
- // 1xn widgets on the same row, which may reduce the space for rendering a
- // widget's description.
- totalHorizontalSpanAfterAddingWidget <= maxSpansPerRow - 1
- && widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))) {
+ // Since the size of the widget cell is determined by dividing the maximum span
+ // pixels evenly, making sure that each widget would have enough span pixels to
+ // show their contents.
+ widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))
+ && widgetItemsAtRow.stream().allMatch(
+ item -> WidgetSizes.getWidgetItemSizePx(context, dp, item)
+ .getWidth() <= individualSpan)
+ && WidgetSizes.getWidgetItemSizePx(context, dp, widgetItem)
+ .getWidth() <= individualSpan) {
// Group items in the same row if
// 1. they are with the same type, i.e. a row can only have widgets or shortcuts but
// never a mix of both.
- // 2. the total number of horizontal spans are smaller than or equal to
- // MAX_SPAN_PER_ROW. If an item has a horizontal span > MAX_SPAN_PER_ROW, we just
- // place it in its own row regardless of the horizontal span limit.
+ // 2. Each widget will have horizontal cell span pixels that is at least as large as
+ // it is required to fit in the horizontal content, unless the widget horizontal
+ // span pixels is larger than the maximum allowed.
+ // If an item has horizontal span pixels larger than the maximum allowed pixels
+ // per row, we just place it in its own row regardless of the horizontal span
+ // limit.
widgetItemsAtRow.add(widgetItem);
} else {
widgetItemsAtRow = new ArrayList<>();
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 19b8b0c..5f516eb 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -29,7 +29,9 @@
import android.content.Intent;
import android.graphics.Point;
+import android.os.SystemClock;
import android.platform.test.annotations.IwTest;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -525,9 +527,11 @@
@Test
@PortraitLandscape
public void testDragAppIconToWorkspaceCell() throws Exception {
+ long startTime, endTime, elapsedTime;
Point[] targets = getCornersAndCenterPositions();
for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
@@ -537,12 +541,21 @@
}
// Reset the workspace for the next shortcut creation.
initialize(this);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime);
}
// test to move a shortcut to other cell.
final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME);
for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
launcherTestAppIcon.dragToWorkspace(target.x, target.y);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to move shortcut to other cell: " + elapsedTime);
}
}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 9dc46f1..e0101f5 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -94,6 +94,7 @@
}).when(mIconCache).getTitleNoCache(any());
mViewHolderBinder = new WidgetsListTableViewHolderBinder(
+ mContext,
LayoutInflater.from(mContext),
mOnIconClickListener,
mOnLongClickListener);
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index 715dcca..d2c2fd7 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
@@ -35,11 +36,13 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
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.util.ActivityContextWrapper;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.util.WidgetsTableUtils;
@@ -57,11 +60,19 @@
public final class WidgetsTableUtilsTest {
private static final String TEST_PACKAGE = "com.google.test";
+ private static final int SPACE_SIZE = 10;
+ private static final int CELL_SIZE = 50;
+ private static final int NUM_OF_COLS = 5;
+ private static final int NUM_OF_ROWS = 5;
+
@Mock
private IconCache mIconCache;
+ @Mock
+ private DeviceProfile mTestDeviceProfile;
+
private Context mContext;
- private InvariantDeviceProfile mTestProfile;
+ private InvariantDeviceProfile mTestInvariantProfile;
private WidgetItem mWidget1x1;
private WidgetItem mWidget2x2;
private WidgetItem mWidget2x3;
@@ -76,12 +87,13 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = getApplicationContext();
+ mContext = new ActivityContextWrapper(getApplicationContext());
- mTestProfile = new InvariantDeviceProfile();
- mTestProfile.numRows = 5;
- mTestProfile.numColumns = 5;
+ mTestInvariantProfile = new InvariantDeviceProfile();
+ mTestInvariantProfile.numColumns = NUM_OF_COLS;
+ mTestInvariantProfile.numRows = NUM_OF_ROWS;
+ initDP();
initTestWidgets();
initTestShortcuts();
@@ -92,17 +104,17 @@
@Test
- public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow5_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding0_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 5);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 0);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3, 2x4
- // Row 2: 4x4
+ // Row 0: 1x1(50px), 2x2(110px)
+ // Row 1: 2x3(110px), 2x4(110px)
+ // Row 2: 4x4(230px)
assertThat(widgetItemInTable).hasSize(3);
assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget2x4);
@@ -110,65 +122,91 @@
}
@Test
- public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding10_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 4);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 10);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3,
- // Row 2: 2x4,
- // Row 3: 4x4
- assertThat(widgetItemInTable).hasSize(4);
- assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
- assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3);
- assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4);
- assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
+ // Row 0: 1x1(50px), 2x2(110px)
+ // Row 1: 2x3(110px), 2x4(110px)
+ // Row 2: 4x4(230px)
+ assertThat(widgetItemInTable).hasSize(5);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3);
+ assertThat(widgetItemInTable.get(3)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(4)).containsExactly(mWidget4x4);
}
@Test
- public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
+ List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
+ mWidget2x2);
+
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 350, 0);
+
+ // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
+ // Row 1: 2x4(110px)
+ // Row 2: 4x4(230px)
+ assertThat(widgetItemInTable).hasSize(3);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+ }
+
+ @Test
+ public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mShortcut3, mWidget2x3, mShortcut1,
mWidget1x1, mShortcut2, mWidget2x4, mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 4);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 350, 0);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3,
- // Row 2: 2x4,
- // Row 3: 4x4
- // Row 4: shortcut3, shortcut1, shortcut2
- assertThat(widgetItemInTable).hasSize(5);
- assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
- assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3);
- assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4);
- assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
- assertThat(widgetItemInTable.get(4)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
+ // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
+ // Row 1: 2x4(110px),
+ // Row 2: 4x4(230px)
+ // Row 3: shortcut3(50px), shortcut1(50px), shortcut2(50px)
+ assertThat(widgetItemInTable).hasSize(4);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+ assertThat(widgetItemInTable.get(3)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
}
@Test
- public void groupWidgetItemsIntoTableWithoutReordering_shouldMaintainTheOrder() {
+ public void groupWidgetItemsIntoTableWithoutReordering_maxSpanPxPerRow220_cellPadding0_shouldMaintainTheOrder() {
List<WidgetItem> widgetItems =
List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4, mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
- widgetItems, /* maxSpansPerRow= */ 5);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 0);
- // Row 0: 4x4
- // Row 1: 2x3, 1x1
- // Row 2: 2x4, 2x2
+ // Row 0: 4x4(230px)
+ // Row 1: 2x3(110px), 1x1(50px)
+ // Row 2: 2x4(110px), 2x2(110px)
assertThat(widgetItemInTable).hasSize(3);
assertThat(widgetItemInTable.get(0)).containsExactly(mWidget4x4);
assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget1x1);
assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4, mWidget2x2);
}
+ private void initDP() {
+ doAnswer(i -> {
+ ((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
+ return null;
+ }).when(mTestDeviceProfile).getCellSize(any(Point.class));
+ when(mTestDeviceProfile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
+ mTestDeviceProfile.cellLayoutBorderSpacePx = new Point(SPACE_SIZE, SPACE_SIZE);
+ when(mTestDeviceProfile.shouldInsetWidgets()).thenReturn(false);
+ }
+
private void initTestWidgets() {
List<Point> widgetSizes = List.of(new Point(1, 1), new Point(2, 2), new Point(2, 3),
new Point(2, 4), new Point(4, 4));
@@ -184,7 +222,7 @@
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
widgetInfo.spanX = widgetSize.x;
widgetInfo.spanY = widgetSize.y;
- widgetItems.add(new WidgetItem(widgetInfo, mTestProfile, mIconCache));
+ widgetItems.add(new WidgetItem(widgetInfo, mTestInvariantProfile, mIconCache));
}
);
mWidget1x1 = widgetItems.get(0);