From 94d5d3cb6c3a12103042aee85bfdeed57e57c1e6 Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Sun, 28 Aug 2022 21:54:04 -0700 Subject: [PATCH] Support for animating A-Z <-> Search. Demo videos (1/5 speed) and APK: https://drive.google.com/drive/folders/1qQNzcoibiFMzxYhvXc7UEHCaBhJg6SjN?resourcekey=0-OWD06iLXg3wf_eWce4rUPA&usp=sharing Bug: 234882587 Bug: 243688989 Test: Manually tested a bunch of cases at 1/10 animation speed. Such as work profile or not, suggested apps enabled/disabled, typing during the animation, going back during the animation, web results injected above apps, etc. Change-Id: Id4f1a858d387bf3a7f9cf2d23564a276544abef1 --- res/layout/all_apps_personal_work_tabs.xml | 4 +- res/layout/search_results_rv_layout.xml | 2 +- res/layout/work_mode_fab.xml | 1 + .../allapps/ActivityAllAppsContainerView.java | 89 ++++-- .../launcher3/allapps/BaseAllAppsAdapter.java | 5 + .../allapps/BaseAllAppsContainerView.java | 9 +- .../launcher3/allapps/FloatingHeaderView.java | 77 ++++-- .../launcher3/allapps/SearchRecyclerView.java | 20 +- .../allapps/SearchTransitionController.java | 258 ++++++++++++++++++ .../search/AppsSearchContainerLayout.java | 3 - .../android/launcher3/ui/WorkProfileTest.java | 7 +- 11 files changed, 417 insertions(+), 58 deletions(-) create mode 100644 src/com/android/launcher3/allapps/SearchTransitionController.java diff --git a/res/layout/all_apps_personal_work_tabs.xml b/res/layout/all_apps_personal_work_tabs.xml index 11143fb3e1..d15b906fb7 100644 --- a/res/layout/all_apps_personal_work_tabs.xml +++ b/res/layout/all_apps_personal_work_tabs.xml @@ -20,6 +20,8 @@ android:layout_width="match_parent" android:layout_height="@dimen/all_apps_header_pill_height" android:layout_gravity="center_horizontal" + android:paddingTop="@dimen/all_apps_tabs_vertical_padding" + android:paddingBottom="@dimen/all_apps_tabs_vertical_padding" android:orientation="horizontal" style="@style/TextHeadline"> @@ -28,7 +30,6 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginEnd="@dimen/all_apps_tabs_button_horizontal_padding" - android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding" android:layout_weight="1" android:background="@drawable/all_apps_tabs_background" android:text="@string/all_apps_personal_tab" @@ -41,7 +42,6 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginStart="@dimen/all_apps_tabs_button_horizontal_padding" - android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding" android:layout_weight="1" android:background="@drawable/all_apps_tabs_background" android:text="@string/all_apps_work_tab" diff --git a/res/layout/search_results_rv_layout.xml b/res/layout/search_results_rv_layout.xml index 567cb5f4fc..9127521090 100644 --- a/res/layout/search_results_rv_layout.xml +++ b/res/layout/search_results_rv_layout.xml @@ -18,7 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/search_results_list_view" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:clipToPadding="false" android:descendantFocusability="afterDescendants" android:focusable="true" /> diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml index d2fa5fa066..81b28ba004 100644 --- a/res/layout/work_mode_fab.xml +++ b/res/layout/work_mode_fab.xml @@ -26,6 +26,7 @@ android:textColor="@color/all_apps_tab_text" android:textSize="14sp" android:background="@drawable/work_apps_toggle_background" + android:forceHasOverlappingRendering="false" android:drawablePadding="8dp" android:drawableStart="@drawable/ic_corp_off" android:layout_marginBottom="@dimen/work_fab_margin_bottom" diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index e33e44e529..aa9cfd16f5 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -15,6 +15,8 @@ */ package com.android.launcher3.allapps; +import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.SEARCH; + import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; @@ -34,7 +36,6 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.views.AppLauncher; import java.util.ArrayList; -import java.util.Objects; /** * All apps container view with search support for use in a dragging activity. @@ -44,6 +45,11 @@ import java.util.Objects; public class ActivityAllAppsContainerView extends BaseAllAppsContainerView { + private static final long DEFAULT_SEARCH_TRANSITION_DURATION_MS = 300; + + // Used to animate Search results out and A-Z apps in, or vice-versa. + private final SearchTransitionController mSearchTransitionController; + protected SearchUiManager mSearchUiManager; /** * View that defines the search box. Result is rendered inside the recycler view defined in the @@ -52,6 +58,7 @@ public class ActivityAllAppsContainerView results) { if (getSearchResultList().setSearchResults(results)) { - for (int i = 0; i < mAH.size(); i++) { - if (mAH.get(i).mRecyclerView != null) { - mAH.get(i).mRecyclerView.onSearchResultsChanged(); - } - } + getSearchRecyclerView().onSearchResultsChanged(); } + if (results != null) { + animateToSearchState(true); + } + } + + private void animateToSearchState(boolean goingToSearch) { + animateToSearchState(goingToSearch, DEFAULT_SEARCH_TRANSITION_DURATION_MS); + } + + private void animateToSearchState(boolean goingToSearch, long durationMs) { + if (!mSearchTransitionController.isRunning() && goingToSearch == isSearching()) { + return; + } + if (goingToSearch) { + // Fade out the button to pause work apps. + mWorkManager.onActivePageChanged(SEARCH); + } + mSearchTransitionController.animateToSearchState(goingToSearch, durationMs, + /* onEndRunnable = */ () -> { + mIsSearching = goingToSearch; + updateSearchResultsVisibility(); + int previousPage = getCurrentPage(); + if (mRebindAdaptersAfterSearchAnimation) { + rebindAdapters(false); + mRebindAdaptersAfterSearchAnimation = false; + } + if (!goingToSearch) { + setSearchResults(null); + if (mViewPager != null) { + mViewPager.setCurrentPage(previousPage); + } + onActivePageChanged(previousPage); + } + }); } @Override @@ -121,6 +151,8 @@ public class ActivityAllAppsContainerView adapterHolder.mRecyclerView) - .filter(Objects::nonNull) - .forEach(v -> { - v.removeItemDecoration(decoration); // Remove in case it is already added. - v.addItemDecoration(decoration); - }); + getSearchRecyclerView().removeItemDecoration(decoration); // In case it is already added. + getSearchRecyclerView().addItemDecoration(decoration); } @Override diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java index 6990e576de..42f8b0ccaa 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java @@ -127,6 +127,11 @@ public abstract class BaseAllAppsAdapter ex public boolean isContentSame(AdapterItem other) { return itemInfo == null && other.itemInfo == null; } + + /** Sets the alpha of the decorator for this item. Returns true if successful. */ + public boolean setDecorationFillAlpha(int alpha) { + return false; + } } protected final T mActivityContext; diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index f3c5dd6d31..760cf705ac 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -107,12 +107,13 @@ public abstract class BaseAllAppsContainerView