Merge "Add shortcuts count as a subtitle in the full widgets sheet" into sc-dev
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 78910ce..3e0bedd 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -926,6 +926,8 @@
// 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;
diff --git a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
index a5ed20a..95fa05f 100644
--- a/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
+++ b/src/com/android/launcher3/widget/picker/SearchAndRecommendationsScrollController.java
@@ -16,10 +16,10 @@
package com.android.launcher3.widget.picker;
import android.view.View;
+import android.view.ViewGroup.MarginLayoutParams;
import android.widget.RelativeLayout;
import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.widget.picker.WidgetsFullSheet.SearchAndRecommendationViewHolder;
@@ -33,20 +33,21 @@
RecyclerViewFastScroller.OnFastScrollChangeListener {
private final boolean mHasWorkProfile;
private final SearchAndRecommendationViewHolder mViewHolder;
- private final RecyclerView mPrimaryRecyclerView;
+ private final WidgetsRecyclerView mPrimaryRecyclerView;
// The following are only non null if mHasWorkProfile is true.
- @Nullable private final RecyclerView mWorkRecyclerView;
+ @Nullable private final WidgetsRecyclerView mWorkRecyclerView;
@Nullable private final View mPrimaryWorkTabsView;
@Nullable private final PersonalWorkPagedView mPrimaryWorkViewPager;
+ private WidgetsRecyclerView mCurrentRecyclerView;
private int mMaxCollapsibleHeight = 0;
SearchAndRecommendationsScrollController(
boolean hasWorkProfile,
SearchAndRecommendationViewHolder viewHolder,
- RecyclerView primaryRecyclerView,
- @Nullable RecyclerView workRecyclerView,
+ WidgetsRecyclerView primaryRecyclerView,
+ @Nullable WidgetsRecyclerView workRecyclerView,
@Nullable View personalWorkTabsView,
@Nullable PersonalWorkPagedView primaryWorkViewPager) {
mHasWorkProfile = hasWorkProfile;
@@ -55,6 +56,12 @@
mWorkRecyclerView = workRecyclerView;
mPrimaryWorkTabsView = personalWorkTabsView;
mPrimaryWorkViewPager = primaryWorkViewPager;
+ mCurrentRecyclerView = mPrimaryRecyclerView;
+ }
+
+ /** Sets the current active {@link WidgetsRecyclerView}. */
+ public void setCurrentRecyclerView(WidgetsRecyclerView currentRecyclerView) {
+ mCurrentRecyclerView = currentRecyclerView;
}
/**
@@ -64,10 +71,10 @@
// The maximum vertical distance, in pixels, until the last collapsible element is not
// visible from the screen when the user scrolls down the recycler view.
mMaxCollapsibleHeight = mViewHolder.mContainer.getPaddingTop()
- + mViewHolder.mCollapseHandle.getMeasuredHeight()
- + mViewHolder.mHeaderTitle.getMeasuredHeight();
+ + measureHeightWithVerticalMargins(mViewHolder.mCollapseHandle)
+ + measureHeightWithVerticalMargins(mViewHolder.mHeaderTitle);
- int topContainerHeight = mViewHolder.mContainer.getMeasuredHeight();
+ int topContainerHeight = measureHeightWithVerticalMargins(mViewHolder.mContainer);
if (mHasWorkProfile) {
// In a work profile setup, the full widget sheet contains the following views:
// ------- -|
@@ -114,8 +121,8 @@
//
// When the views are first inflated, the sum of topOffsetAfterAllViewsCollapsed and
// mMaxCollapsibleDistance should equal to the top container height.
- int tabsViewActualHeight =
- mPrimaryWorkTabsView.getMeasuredHeight() - mPrimaryWorkTabsView.getPaddingTop();
+ int tabsViewActualHeight = measureHeightWithVerticalMargins(mPrimaryWorkTabsView)
+ - mPrimaryWorkTabsView.getPaddingTop();
int topOffsetAfterAllViewsCollapsed =
topContainerHeight + tabsViewActualHeight - mMaxCollapsibleHeight;
@@ -149,9 +156,12 @@
* views (e.g. recycler views, tabs) upon scrolling.
*/
@Override
- public void onThumbOffsetYChanged(int y) {
+ public void onThumbOffsetYChanged(int unused) {
+ // Always use the recycler view offset because fast scroller offset has a different scale.
+ int recyclerViewYOffset = mCurrentRecyclerView.getCurrentScrollY();
+ if (recyclerViewYOffset < 0) return;
if (mMaxCollapsibleHeight > 0) {
- int yDisplacement = Math.max(-y, -mMaxCollapsibleHeight);
+ int yDisplacement = Math.max(-recyclerViewYOffset, -mMaxCollapsibleHeight);
mViewHolder.mHeaderTitle.setTranslationY(yDisplacement);
mViewHolder.mSearchBar.setTranslationY(yDisplacement);
if (mHasWorkProfile) {
@@ -159,4 +169,20 @@
}
}
}
+
+ /** Resets any previous view translation. */
+ public void reset() {
+ mViewHolder.mHeaderTitle.setTranslationY(0);
+ mViewHolder.mSearchBar.setTranslationY(0);
+ if (mHasWorkProfile) {
+ mPrimaryWorkTabsView.setTranslationY(0);
+ }
+ }
+
+ /** private the height, in pixel, + the vertical margins of a given view. */
+ private static int measureHeightWithVerticalMargins(View view) {
+ MarginLayoutParams marginLayoutParams = (MarginLayoutParams) view.getLayoutParams();
+ return view.getMeasuredHeight() + marginLayoutParams.bottomMargin
+ + marginLayoutParams.topMargin;
+ }
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 91b79f9..52a2fc5 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -149,7 +149,10 @@
@Override
public void onActivePageChanged(int currentActivePage) {
- mAdapters.get(currentActivePage).mWidgetsRecyclerView.bindFastScrollbar();
+ WidgetsRecyclerView currentRecyclerView =
+ mAdapters.get(currentActivePage).mWidgetsRecyclerView;
+ currentRecyclerView.bindFastScrollbar();
+ mSearchAndRecommendationsScrollController.setCurrentRecyclerView(currentRecyclerView);
reset();
}
@@ -159,6 +162,7 @@
if (mHasWorkProfile) {
mAdapters.get(AdapterHolder.WORK).mWidgetsRecyclerView.scrollToTop();
}
+ mSearchAndRecommendationsScrollController.reset();
}
@VisibleForTesting
@@ -241,6 +245,12 @@
mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
maxSpansPerRow);
}
+
+ if (mInitialTabsHeight == 0 && mTabsView != null) {
+ mInitialTabsHeight = measureHeightWithVerticalMargins(mTabsView);
+ }
+
+ mSearchAndRecommendationsScrollController.updateMarginAndPadding();
}
@Override
@@ -255,12 +265,6 @@
contentLeft + contentWidth, height);
setTranslationShift(mTranslationShift);
-
- if (mInitialTabsHeight == 0 && mTabsView != null) {
- mInitialTabsHeight = mTabsView.getMeasuredHeight();
- }
-
- mSearchAndRecommendationsScrollController.updateMarginAndPadding();
}
@Override
@@ -371,7 +375,14 @@
// No need to check work profile here because mInitialTabHeight is always 0 if there is no
// work profile.
return mInitialTabsHeight
- + mSearchAndRecommendationViewHolder.mContainer.getMeasuredHeight();
+ + measureHeightWithVerticalMargins(mSearchAndRecommendationViewHolder.mContainer);
+ }
+
+ /** private the height, in pixel, + the vertical margins of a given view. */
+ private static int measureHeightWithVerticalMargins(View view) {
+ MarginLayoutParams marginLayoutParams = (MarginLayoutParams) view.getLayoutParams();
+ return view.getMeasuredHeight() + marginLayoutParams.bottomMargin
+ + marginLayoutParams.topMargin;
}
/** A holder class for holding adapters & their corresponding recycler view. */
diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java b/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java
new file mode 100644
index 0000000..d12782c
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/search/WidgetsPickerSearchPipeline.java
@@ -0,0 +1,44 @@
+/*
+ * 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.picker.search;
+
+import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * An interface for a pipeline to handle widgets search.
+ */
+public interface WidgetsPickerSearchPipeline {
+
+ /**
+ * Performs a search query asynchronically. Invokes {@code callback} when the search is
+ * complete.
+ */
+ void query(String input, Consumer<List<WidgetsListBaseEntry>> callback);
+
+ /**
+ * Cancels any ongoing search request.
+ */
+ default void cancel() {};
+
+ /**
+ * Cleans up after search is no longer needed.
+ */
+ default void destroy() {};
+}
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index 5e41d43d..63220ad 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -17,6 +17,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -77,6 +78,17 @@
mDevice.executeShellCommand("pm remove-user " + mProfileUserId);
}
+ @After
+ public void resumeAppStoreUpdate() {
+ executeOnLauncher(launcher -> {
+ if (launcher == null || launcher.getAppsView() == null) {
+ return;
+ }
+ launcher.getAppsView().getAppsStore().disableDeferUpdates(DEFER_UPDATES_TEST);
+ Log.d(TestProtocol.WORK_PROFILE_REMOVED, "resuming AppStore updates");
+ });
+ }
+
@Test
public void workTabExists() {
mDevice.pressHome();
@@ -145,6 +157,12 @@
"work profile status (" + mProfileUserId + ") :"
+ launcher.getAppsView().isWorkTabVisible()));
+
+ executeOnLauncher(launcher -> {
+ launcher.getAppsView().getAppsStore().enableDeferUpdates(DEFER_UPDATES_TEST);
+ Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Defer all apps update");
+ });
+
AtomicInteger attempt = new AtomicInteger(0);
// verify work edu is seen next
waitForLauncherCondition("Launcher did not show the next edu screen", l -> {
@@ -157,7 +175,6 @@
if (((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage()
!= WORK_PAGE) {
Log.d(TestProtocol.WORK_PROFILE_REMOVED, "Work page not highlighted");
- return false;
}
return ((TextView) workEduView.findViewById(R.id.content_text)).getText().equals(
l.getResources().getString(R.string.work_profile_edu_work_apps));