diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java index 7e52ea1372..7cdca746da 100644 --- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java +++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java @@ -120,10 +120,6 @@ public class WidgetPickerActivity extends BaseActivity { WindowInsetsController wc = mDragLayer.getWindowInsetsController(); wc.hide(navigationBars() + statusBars()); - BaseWidgetSheet widgetSheet = WidgetsFullSheet.show(this, true); - widgetSheet.disableNavBarScrim(true); - widgetSheet.addOnCloseListener(this::finish); - parseIntentExtras(); refreshAndBindWidgets(); } @@ -224,9 +220,10 @@ public class WidgetPickerActivity extends BaseActivity { }; } - /** Updates the model with widgets and provides them after applying the provided filter. */ + /** Updates the model with widgets, applies filters and launches the widgets sheet once + * widgets are available */ private void refreshAndBindWidgets() { - MODEL_EXECUTOR.execute(() -> { + MODEL_EXECUTOR.getHandler().postDelayed(() -> { LauncherAppState app = LauncherAppState.getInstance(this); mModel.update(app, null); final List allWidgets = @@ -240,6 +237,9 @@ public class WidgetPickerActivity extends BaseActivity { } ); bindWidgets(allWidgets); + // Open sheet once widgets are available, so that it doesn't interrupt the open + // animation. + openWidgetsSheet(); if (mUiSurface != null) { Map allWidgetItems = allWidgets.stream() .filter(entry -> entry instanceof WidgetsListContentEntry) @@ -253,15 +253,26 @@ public class WidgetPickerActivity extends BaseActivity { mUiSurface, allWidgetItems); mWidgetPredictionsRequester.request(mAddedWidgets, this::bindRecommendedWidgets); } - }); + }, mDeviceProfile.bottomSheetOpenDuration); } private void bindWidgets(List widgets) { MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(widgets)); } + private void openWidgetsSheet() { + MAIN_EXECUTOR.execute(() -> { + BaseWidgetSheet widgetSheet = WidgetsFullSheet.show(this, true); + widgetSheet.disableNavBarScrim(true); + widgetSheet.addOnCloseListener(this::finish); + }); + } + private void bindRecommendedWidgets(List recommendedWidgets) { - MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets)); + // Bind recommendations once picker has finished open animation. + MAIN_EXECUTOR.getHandler().postDelayed( + () -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets), + mDeviceProfile.bottomSheetOpenDuration); } @Override diff --git a/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java index 5730273d88..41fcf61d81 100644 --- a/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java +++ b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java @@ -65,6 +65,7 @@ public class WidgetPredictionsRequester { private final Context mContext; @NonNull private final String mUiSurface; + private boolean mPredictionsAvailable; @NonNull private final Map mAllWidgets; @@ -76,8 +77,8 @@ public class WidgetPredictionsRequester { } /** - * Requests predictions from the app predictions manager and registers the provided callback to - * receive updates when predictions are available. + * Requests one time predictions from the app predictions manager and invokes provided callback + * once predictions are available. * * @param existingWidgets widgets that are currently added to the surface; * @param callback consumer of prediction results to be called when predictions are @@ -159,10 +160,14 @@ public class WidgetPredictionsRequester { @WorkerThread private void bindPredictions(List targets, Predicate filter, Consumer> callback) { - List filteredPredictions = filterPredictions(targets, mAllWidgets, filter); - List mappedPredictions = mapWidgetItemsToItemInfo(filteredPredictions); + if (!mPredictionsAvailable) { + mPredictionsAvailable = true; + List filteredPredictions = filterPredictions(targets, mAllWidgets, filter); + List mappedPredictions = mapWidgetItemsToItemInfo(filteredPredictions); - MAIN_EXECUTOR.execute(() -> callback.accept(mappedPredictions)); + MAIN_EXECUTOR.execute(() -> callback.accept(mappedPredictions)); + MODEL_EXECUTOR.execute(this::clear); + } } /** @@ -214,5 +219,6 @@ public class WidgetPredictionsRequester { mAppPredictor.destroy(); mAppPredictor = null; } + mPredictionsAvailable = false; } } diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java index 13680846f9..c59e295c5f 100644 --- a/src/com/android/launcher3/widget/BaseWidgetSheet.java +++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java @@ -331,8 +331,21 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView * status bar, into account. */ protected void doMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthUsed = getInsetsWidth(); + DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); + measureChildWithMargins(mContent, widthMeasureSpec, + widthUsed, heightMeasureSpec, deviceProfile.bottomSheetTopPadding); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), + MeasureSpec.getSize(heightMeasureSpec)); + } + + /** + * Returns the width used on left and right by the insets / padding. + */ + protected int getInsetsWidth() { int widthUsed; + DeviceProfile deviceProfile = mActivityContext.getDeviceProfile(); if (deviceProfile.isTablet) { widthUsed = Math.max(2 * getTabletHorizontalMargin(deviceProfile), 2 * (mInsets.left + mInsets.right)); @@ -343,11 +356,7 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView widthUsed = Math.max(padding.left + padding.right, 2 * (mInsets.left + mInsets.right)); } - - measureChildWithMargins(mContent, widthMeasureSpec, - widthUsed, heightMeasureSpec, deviceProfile.bottomSheetTopPadding); - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), - MeasureSpec.getSize(heightMeasureSpec)); + return widthUsed; } /** Returns the horizontal margins to be applied to the widget sheet. **/ diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index 9929892e28..fd15677ab7 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -55,7 +55,6 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.compat.AccessibilityManagerCompat; @@ -416,19 +415,18 @@ public class WidgetsFullSheet extends BaseWidgetSheet @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int availableWidth = MeasureSpec.getSize(widthMeasureSpec); + updateMaxSpansPerRow(availableWidth); doMeasure(widthMeasureSpec, heightMeasureSpec); - - if (updateMaxSpansPerRow()) { - doMeasure(widthMeasureSpec, heightMeasureSpec); - } } - /** Returns {@code true} if the max spans have been updated. */ - private boolean updateMaxSpansPerRow() { - if (getMeasuredWidth() == 0) return false; - - @Px int maxHorizontalSpan = getContentView().getMeasuredWidth() - - (2 * mContentHorizontalMargin); + /** Returns {@code true} if the max spans have been updated. + * + * @param availableWidth Total width available within parent (includes insets). + */ + private void updateMaxSpansPerRow(int availableWidth) { + @Px int maxHorizontalSpan = getAvailableWidthForSuggestions( + availableWidth - getInsetsWidth()); if (mMaxSpanPerRow != maxHorizontalSpan) { mMaxSpanPerRow = maxHorizontalSpan; mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow( @@ -439,16 +437,15 @@ public class WidgetsFullSheet extends BaseWidgetSheet mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow( maxHorizontalSpan); } - onRecommendedWidgetsBound(); - return true; + post(this::onRecommendedWidgetsBound); } - return false; } - protected View getContentView() { - return mHasWorkProfile - ? mViewPager - : mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView; + /** + * Returns the width available to display suggestions. + */ + protected int getAvailableWidthForSuggestions(int pickerAvailableWidth) { + return pickerAvailableWidth - (2 * mContentHorizontalMargin); } @Override @@ -493,7 +490,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet .mWidgetsListAdapter.hasVisibleEntries()); if (mIsNoWidgetsViewNeeded != isNoWidgetsViewNeeded) { mIsNoWidgetsViewNeeded = isNoWidgetsViewNeeded; - onRecommendedWidgetsBound(); + post(this::onRecommendedWidgetsBound); } } @@ -549,7 +546,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet mAdapters.get(AdapterHolder.SEARCH).mWidgetsRecyclerView.setVisibility(GONE); // Visibility of recommended widgets, recycler views and headers are handled in methods // below. - onRecommendedWidgetsBound(); + post(this::onRecommendedWidgetsBound); onWidgetsBound(); } } diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java index ae8b5dbd15..840d98a271 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java @@ -322,6 +322,30 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet { * RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE; } + @Override + @Px + protected int getAvailableWidthForSuggestions(int pickerAvailableWidth) { + int rightPaneWidth = (int) Math.ceil(0.67 * pickerAvailableWidth); + + if (mDeviceProfile.isTwoPanels && enableUnfoldedTwoPanePicker()) { + // See onLayout + int leftPaneWidth = (int) (0.33 * pickerAvailableWidth); + @Px int minLeftPaneWidthPx = Utilities.dpToPx(MINIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP); + @Px int maxLeftPaneWidthPx = Utilities.dpToPx(MAXIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP); + if (leftPaneWidth < minLeftPaneWidthPx) { + leftPaneWidth = minLeftPaneWidthPx; + } else if (leftPaneWidth > maxLeftPaneWidthPx) { + leftPaneWidth = maxLeftPaneWidthPx; + } + rightPaneWidth = pickerAvailableWidth - leftPaneWidth; + } + + // Since suggestions are shown in right pane, the available width is 2/3 of total width of + // bottom sheet. + return rightPaneWidth - getResources().getDimensionPixelSize( + R.dimen.widget_list_horizontal_margin_two_pane); // right pane end margin. + } + @Override public void onActivePageChanged(int currentActivePage) { super.onActivePageChanged(currentActivePage); @@ -384,11 +408,6 @@ public class WidgetsTwoPaneSheet extends WidgetsFullSheet { } - @Override - protected View getContentView() { - return mRightPane; - } - private HeaderChangeListener getHeaderChangeListener() { return new HeaderChangeListener() { @Override