From a1af2cee1cf335ac193a978fd81791cbce0f21f4 Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Tue, 12 Mar 2024 10:23:59 -0700 Subject: [PATCH] Instead of popup to show letters, show private space icon on fast scrolling Use spannableString to show the icon instead of regular letters for the private space icons. bug:304752744 Test manual: https://drive.google.com/file/d/1LFy4-bu69Kuo8eV4erjJOsbkiQJs09kC/view?usp=sharing Flag: None Change-Id: I149d7aba6b0a4fdafacd2684e56827c7e1b9d724 --- .../ic_private_profile_app_scroller_badge.xml | 28 +++++++++++++++++++ .../launcher3/FastScrollRecyclerView.java | 12 +------- .../allapps/AllAppsRecyclerView.java | 2 +- .../allapps/AlphabeticalAppsList.java | 21 ++++++++++---- .../views/RecyclerViewFastScroller.java | 7 +++-- .../widget/picker/WidgetsRecyclerView.java | 2 +- 6 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 res/drawable/ic_private_profile_app_scroller_badge.xml diff --git a/res/drawable/ic_private_profile_app_scroller_badge.xml b/res/drawable/ic_private_profile_app_scroller_badge.xml new file mode 100644 index 0000000000..b52a277aa6 --- /dev/null +++ b/res/drawable/ic_private_profile_app_scroller_badge.xml @@ -0,0 +1,28 @@ + + + + + diff --git a/src/com/android/launcher3/FastScrollRecyclerView.java b/src/com/android/launcher3/FastScrollRecyclerView.java index 51c7a055ca..eff748a2b0 100644 --- a/src/com/android/launcher3/FastScrollRecyclerView.java +++ b/src/com/android/launcher3/FastScrollRecyclerView.java @@ -155,7 +155,7 @@ public abstract class FastScrollRecyclerView extends RecyclerView { * Maps the touch (from 0..1) to the adapter position that should be visible. *

Override in each subclass of this base class. */ - public abstract String scrollToPositionAtProgress(float touchFraction); + public abstract CharSequence scrollToPositionAtProgress(float touchFraction); /** * Updates the bounds for the scrollbar. @@ -193,14 +193,4 @@ public abstract class FastScrollRecyclerView extends RecyclerView { } scrollToPosition(0); } - - /** - * Scrolls this recycler view to the bottom with easing and duration. - */ - public void scrollToBottomWithMotion(int duration) { - if (mScrollbar != null) { - mScrollbar.reattachThumbToScroll(); - } - smoothScrollBy(0, getAvailableScrollHeight(), Interpolators.EMPHASIZED, duration); - } } diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 36a44cc345..ba34f598e7 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -180,7 +180,7 @@ public class AllAppsRecyclerView extends FastScrollRecyclerView { * Maps the touch (from 0..1) to the adapter position that should be visible. */ @Override - public String scrollToPositionAtProgress(float touchFraction) { + public CharSequence scrollToPositionAtProgress(float touchFraction) { int rowCount = mApps.getNumAppRows(); if (rowCount == 0) { return ""; diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 4d4b8d282d..60df7c529c 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -22,6 +22,10 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.ImageSpan; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -65,11 +69,11 @@ public class AlphabeticalAppsList implement */ public static class FastScrollSectionInfo { // The section name - public final String sectionName; + public final CharSequence sectionName; // The item position public final int position; - public FastScrollSectionInfo(String sectionName, int position) { + public FastScrollSectionInfo(CharSequence sectionName, int position) { this.sectionName = sectionName; this.position = position; } @@ -93,6 +97,7 @@ public class AlphabeticalAppsList implement // The of ordered component names as a result of a search query private final ArrayList mSearchResults = new ArrayList<>(); + private final SpannableString mPrivateProfileAppScrollerBadge; private BaseAllAppsAdapter mAdapter; private AppInfoComparator mAppNameComparator; private int mNumAppsPerRowAllApps; @@ -110,6 +115,10 @@ public class AlphabeticalAppsList implement if (mAllAppsStore != null) { mAllAppsStore.addUpdateListener(this); } + mPrivateProfileAppScrollerBadge = new SpannableString(" "); + mPrivateProfileAppScrollerBadge.setSpan(new ImageSpan(context, + R.drawable.ic_private_profile_app_scroller_badge, ImageSpan.ALIGN_CENTER), + 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } /** Set the number of apps per row when device profile changes. */ @@ -383,6 +392,7 @@ public class AlphabeticalAppsList implement private int addAppsWithSections(List appList, int startPosition) { String lastSectionName = null; boolean hasPrivateApps = false; + int position = startPosition; if (mPrivateProviderManager != null) { hasPrivateApps = appList.stream(). allMatch(mPrivateProviderManager.getItemInfoMatcher()); @@ -403,11 +413,12 @@ public class AlphabeticalAppsList implement // Create a new section if the section names do not match if (!sectionName.equals(lastSectionName)) { lastSectionName = sectionName; - mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, startPosition)); + mFastScrollerSections.add(new FastScrollSectionInfo(hasPrivateApps ? + mPrivateProfileAppScrollerBadge : sectionName, position)); } - startPosition++; + position++; } - return startPosition; + return position; } /** diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java index 8408cc760d..df8f635525 100644 --- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java +++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java @@ -30,6 +30,7 @@ import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.Property; @@ -121,7 +122,7 @@ public class RecyclerViewFastScroller extends View { // Fast scroller popup private TextView mPopupView; private boolean mPopupVisible; - private String mPopupSectionName; + private CharSequence mPopupSectionName; private Insets mSystemGestureInsets; protected FastScrollRecyclerView mRv; @@ -307,13 +308,13 @@ public class RecyclerViewFastScroller extends View { // Update the fastscroller section name at this touch position int bottom = mRv.getScrollbarTrackHeight() - mThumbHeight; float boundedY = (float) Math.max(0, Math.min(bottom, y - mTouchOffsetY)); - String sectionName = mRv.scrollToPositionAtProgress(boundedY / bottom); + CharSequence sectionName = mRv.scrollToPositionAtProgress(boundedY / bottom); if (!sectionName.equals(mPopupSectionName)) { mPopupSectionName = sectionName; mPopupView.setText(sectionName); performHapticFeedback(CLOCK_TICK); } - animatePopupVisibility(!sectionName.isEmpty()); + animatePopupVisibility(!TextUtils.isEmpty(sectionName)); mLastTouchY = boundedY; setThumbOffsetY((int) mLastTouchY); } diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java index 698e76498a..a47818f6c2 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java +++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java @@ -73,7 +73,7 @@ public class WidgetsRecyclerView extends FastScrollRecyclerView implements OnIte * Maps the touch (from 0..1) to the adapter position that should be visible. */ @Override - public String scrollToPositionAtProgress(float touchFraction) { + public CharSequence scrollToPositionAtProgress(float touchFraction) { // Skip early if widgets are not bound. if (isModelNotReady()) { return "";