Pause page scrolls while new recommendation are being applied
http://screencast/cast/NDg4NzU2MjI3NDQ3MTkzNnw5MTU1NTc4Yy1lYw
http://screencast/cast/NDk5Nzg4MzQ5MjMwMjg0OHxmZGM0MGZlYS0wMg
This cl is NO-OP for anything else using it already. Just renamed it.
Bug: 318410881
Test: Manual (see screencast)
Flag: ACONFIG com.android.launcher3.enable_categorized_widget_recommendations DEVELOPMENT
Change-Id: I55d599437b2554f58d635d11f2b603516b030f30
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index 0e38007..9867556 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -132,7 +132,7 @@
launcher.viewCache.setCacheSize(R.layout.folder_page, 2)
TraceHelper.INSTANCE.endSection()
launcher.workspace.removeExtraEmptyScreen(/* stripEmptyScreens= */ true)
- launcher.workspace.pageIndicator.setAreScreensBinding(false, deviceProfile.isTwoPanels)
+ launcher.workspace.pageIndicator.setPauseScroll(/*pause=*/ false, deviceProfile.isTwoPanels)
}
/**
@@ -299,8 +299,8 @@
}
override fun bindScreens(orderedScreenIds: LIntArray) {
- launcher.workspace.pageIndicator.setAreScreensBinding(
- true,
+ launcher.workspace.pageIndicator.setPauseScroll(
+ /*pause=*/ true,
launcher.deviceProfile.isTwoPanels
)
val firstScreenPosition = 0
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 30156c8..0640bf3 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -27,10 +27,12 @@
void setMarkersCount(int numMarkers);
/**
- * Sets flag to indicate when the screens are in the process of binding so that we don't animate
- * during that period.
+ * Sets a flag indicating whether to pause scroll.
+ * <p>Should be set to {@code true} while the screen is binding or new data is being applied,
+ * and to {@code false} once done. This prevents animation conflicts due to scrolling during
+ * those periods.</p>
*/
- default void setAreScreensBinding(boolean areScreensBinding, boolean isTwoPanels) {
+ default void setPauseScroll(boolean pause, boolean isTwoPanels) {
// No-op by default
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 1b5abaa..77effca 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -130,7 +130,7 @@
*/
private float mCurrentPosition;
private float mFinalPosition;
- private boolean mAreScreensBinding;
+ private boolean mIsScrollPaused;
private boolean mIsTwoPanels;
private ObjectAnimator mAnimator;
private @Nullable ObjectAnimator mAlphaAnimator;
@@ -172,7 +172,7 @@
}
// Skip scroll update during binding. We will update it when binding completes.
- if (mAreScreensBinding) {
+ if (mIsScrollPaused) {
return;
}
@@ -376,15 +376,15 @@
}
@Override
- public void setAreScreensBinding(boolean areScreensBinding, boolean isTwoPanels) {
+ public void setPauseScroll(boolean pause, boolean isTwoPanels) {
mIsTwoPanels = isTwoPanels;
// Reapply correct current position which was skipped during setScroll.
- if (mAreScreensBinding && !areScreensBinding) {
+ if (mIsScrollPaused && !pause) {
CURRENT_POSITION.set(this, (float) mActivePage);
}
- mAreScreensBinding = areScreensBinding;
+ mIsScrollPaused = pause;
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
index 738d74e..426a3ae 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
@@ -29,7 +29,6 @@
import androidx.annotation.Px;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.model.WidgetItem;
@@ -88,6 +87,7 @@
* Displays all the provided recommendations in a single table if they fit.
*
* @param recommendedWidgets list of widgets to be displayed in recommendation section.
+ * @param deviceProfile the current {@link DeviceProfile}
* @param availableHeight height in px that can be used to display the recommendations;
* recommendations that don't fit in this height won't be shown
* @param availableWidth width in px that the recommendations should display in
@@ -96,12 +96,13 @@
* @return {@code false} if no recommendations could fit in the available space.
*/
public boolean setRecommendations(
- List<WidgetItem> recommendedWidgets, final @Px float availableHeight,
- final @Px int availableWidth, final @Px int cellPadding) {
+ List<WidgetItem> recommendedWidgets, DeviceProfile deviceProfile,
+ final @Px float availableHeight, final @Px int availableWidth,
+ final @Px int cellPadding) {
this.mAvailableHeight = availableHeight;
removeAllViews();
- maybeDisplayInTable(recommendedWidgets, availableWidth, cellPadding);
+ maybeDisplayInTable(recommendedWidgets, deviceProfile, availableWidth, cellPadding);
updateTitleAndIndicator();
return getChildCount() > 0;
}
@@ -111,6 +112,7 @@
* <p>In case of a single category, no title is displayed for it.</p>
*
* @param recommendations a map of widget items per recommendation category
+ * @param deviceProfile the current {@link DeviceProfile}
* @param availableHeight height in px that can be used to display the recommendations;
* recommendations that don't fit in this height won't be shown
* @param availableWidth width in px that the recommendations should display in
@@ -120,10 +122,12 @@
*/
public boolean setRecommendations(
Map<WidgetRecommendationCategory, List<WidgetItem>> recommendations,
+ DeviceProfile deviceProfile,
final @Px float availableHeight, final @Px int availableWidth,
final @Px int cellPadding) {
this.mAvailableHeight = availableHeight;
Context context = getContext();
+ mPageIndicator.setPauseScroll(true, deviceProfile.isTwoPanels);
removeAllViews();
int displayedCategories = 0;
@@ -133,7 +137,7 @@
new TreeMap<>(recommendations).entrySet()) {
// If none of the recommendations for the category could fit in the mAvailableHeight, we
// don't want to add that category; and we look for the next one.
- if (maybeDisplayInTable(entry.getValue(), availableWidth, cellPadding)) {
+ if (maybeDisplayInTable(entry.getValue(), deviceProfile, availableWidth, cellPadding)) {
mCategoryTitles.add(
context.getResources().getString(entry.getKey().categoryTitleRes));
displayedCategories++;
@@ -145,14 +149,21 @@
}
updateTitleAndIndicator();
+ mPageIndicator.setPauseScroll(false, deviceProfile.isTwoPanels);
return getChildCount() > 0;
}
/** Displays the page title and paging indicator if there are multiple pages. */
private void updateTitleAndIndicator() {
- int titleAndIndicatorVisibility = getPageCount() > 1 ? View.VISIBLE : View.GONE;
+ boolean showPaginatedView = getPageCount() > 1;
+ int titleAndIndicatorVisibility = showPaginatedView ? View.VISIBLE : View.GONE;
mRecommendationPageTitle.setVisibility(titleAndIndicatorVisibility);
mPageIndicator.setVisibility(titleAndIndicatorVisibility);
+ if (showPaginatedView) {
+ mPageIndicator.setActiveMarker(0);
+ setCurrentPage(0);
+ mRecommendationPageTitle.setText(mCategoryTitles.get(0));
+ }
}
@Override
@@ -218,9 +229,9 @@
* <p>Returns false if none of the recommendations could fit.</p>
*/
private boolean maybeDisplayInTable(List<WidgetItem> recommendedWidgets,
+ DeviceProfile deviceProfile,
final @Px int availableWidth, final @Px int cellPadding) {
Context context = getContext();
- DeviceProfile deviceProfile = Launcher.getLauncher(context).getDeviceProfile();
LayoutInflater inflater = LayoutInflater.from(context);
List<ArrayList<WidgetItem>> rows = groupWidgetItemsUsingRowPxWithoutReordering(
@@ -239,7 +250,7 @@
recommendationsTable.setWidgetCellLongClickListener(mWidgetCellOnLongClickListener);
boolean displayedAtLeastOne = recommendationsTable.setRecommendedWidgets(rows,
- mAvailableHeight);
+ deviceProfile, mAvailableHeight);
if (displayedAtLeastOne) {
addView(recommendationsTable);
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 237078e..f5742af 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -590,6 +590,7 @@
if (enableCategorizedWidgetSuggestions()) {
mHasRecommendedWidgets = mWidgetRecommendationsView.setRecommendations(
mActivityContext.getPopupDataProvider().getCategorizedRecommendedWidgets(),
+ mDeviceProfile,
/* availableHeight= */ getMaxAvailableHeightForRecommendations(),
/* availableWidth= */ mMaxSpanPerRow,
/* cellPadding= */ mWidgetCellHorizontalPadding
@@ -597,6 +598,7 @@
} else {
mHasRecommendedWidgets = mWidgetRecommendationsView.setRecommendations(
mActivityContext.getPopupDataProvider().getRecommendedWidgets(),
+ mDeviceProfile,
/* availableHeight= */ getMaxAvailableHeightForRecommendations(),
/* availableWidth= */ mMaxSpanPerRow,
/* cellPadding= */ mWidgetCellHorizontalPadding
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index ce1f4e0..47750a5 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -32,7 +32,6 @@
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.widget.WidgetCell;
@@ -89,9 +88,11 @@
* <p>Returns {@code false} if none of the widgets could fit</p>
*/
public boolean setRecommendedWidgets(List<ArrayList<WidgetItem>> recommendedWidgets,
+ DeviceProfile deviceProfile,
float recommendationTableMaxHeight) {
mRecommendationTableMaxHeight = recommendationTableMaxHeight;
RecommendationTableData data = fitRecommendedWidgetsToTableSpace(/* previewScale= */ 1f,
+ deviceProfile,
recommendedWidgets);
bindData(data);
return !data.mRecommendationTable.isEmpty();
@@ -144,6 +145,7 @@
private RecommendationTableData fitRecommendedWidgetsToTableSpace(
float previewScale,
+ DeviceProfile deviceProfile,
List<ArrayList<WidgetItem>> recommendedWidgetsInTable) {
if (previewScale < MAX_DOWN_SCALE_RATIO) {
Log.w(TAG, "Hide recommended widgets. Can't down scale previews to " + previewScale);
@@ -151,7 +153,6 @@
}
// A naive estimation of the widgets recommendation table height without inflation.
float totalHeight = mWidgetsRecommendationTableVerticalPadding;
- DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
for (int i = 0; i < recommendedWidgetsInTable.size(); i++) {
List<WidgetItem> widgetItems = recommendedWidgetsInTable.get(i);
float rowHeight = 0;
@@ -175,12 +176,14 @@
// num of row by 1 to see if it fits.
return fitRecommendedWidgetsToTableSpace(
previewScale,
+ deviceProfile,
recommendedWidgetsInTable.subList(/* fromIndex= */0,
/* toIndex= */recommendedWidgetsInTable.size() - 1));
}
float nextPreviewScale = previewScale * DOWN_SCALE_RATIO;
- return fitRecommendedWidgetsToTableSpace(nextPreviewScale, recommendedWidgetsInTable);
+ return fitRecommendedWidgetsToTableSpace(nextPreviewScale, deviceProfile,
+ recommendedWidgetsInTable);
}
/** Data class for the widgets recommendation table and widgets preview scaling. */