From 5da04b231fba55310da38a354f44df9a2a4255bd Mon Sep 17 00:00:00 2001 From: Brandon Dayauon Date: Fri, 5 Apr 2024 08:31:28 -0700 Subject: [PATCH] Fix stale header height being used in scroll to header calculation - This fixes the inconsistency of how far down is needed to scroll to since the values used to calculate the header during drawOnScrimWithScaleAndBottomOffset() is faulty. - Tweaked the row to scroll to when there are tabs vs no tabs. When there are no tabs, its possible the header gets cut off most of the time hence subtracting by 1 will help this problem. bug:332543940 Test locally: https://screenshot.googleplex.com/5y4vYiQcnSMKcA6 manual - before: https://drive.google.com/file/d/14Zj_FyO-3bVfXwuxaqgG_DXMELYS5bQn/view?usp=sharing after with tabs: after 5x5: https://drive.google.com/file/d/16rjaut6VqBMxG6uLQSnVTLRhUQnAANZ5/view?usp=sharing after 4x5: https://drive.google.com/file/d/16jCPN8BewwuIQobt0t6tdVouUKpp1CdI/view?usp=sharing after 4x4: https://drive.google.com/file/d/16VFQb5s6IfrpjRU9PmLlAJWjh1zIo77o/view?usp=sharing after 3x3: https://drive.google.com/file/d/16VFQb5s6IfrpjRU9PmLlAJWjh1zIo77o/view?usp=sharing after 2x2: https://drive.google.com/file/d/16N6Myuv9VtXgI1p4sIuV23iupea7jYLQ/view?usp=sharing after no tabs: after 5x5: https://drive.google.com/file/d/17H1oF_9fJnrtSqmJJqQyyn4upuM2CsoG/view?usp=sharing after 4x5: https://drive.google.com/file/d/178Vu3SvnvSPODIfaR0oz6-jPVYDDNMaA/view?usp=sharing after 4x4: https://drive.google.com/file/d/16yt_5ePPR7kwSrZlo5Sj3x0DqHoQKqYP/view?usp=sharing after 3x3: https://drive.google.com/file/d/17HqebtHWcEHg-i9AfqHEVdl4YnQhX06P/view?usp=sharing after 2x2: https://drive.google.com/file/d/17HqebtHWcEHg-i9AfqHEVdl4YnQhX06P/view?usp=sharing after tablet: landscape: https://drive.google.com/file/d/16JQGs0A3ifKpgqrpQwIzssrXbH-OC0Ej/view?usp=sharing portrait: https://drive.google.com/file/d/16LmLnOEB6XkuAkAcgvP2mKHe5QQqG1oh/view?usp=sharing Flag: ACONFIG com.android.launcher3.Flags.private_space_animation TRUNKFOOD Change-Id: If8a70cc71e9cff4a7f8d3b648e3e59c414e40ee5 --- .../allapps/ActivityAllAppsContainerView.java | 22 ++++++----- .../launcher3/allapps/FloatingHeaderView.java | 9 ++++- .../allapps/PrivateProfileManager.java | 5 ++- .../allapps/PrivateSpaceHeaderViewTest.java | 39 +++++++++++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java index c255eb54a7..8026d4acfb 100644 --- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java @@ -191,7 +191,6 @@ public class ActivityAllAppsContainerView private float mBottomSheetAlpha = 1f; private boolean mForceBottomSheetVisible; private int mTabsProtectionAlpha; - private float mTotalHeaderProtectionHeight; @Nullable private AllAppsTransitionController mAllAppsTransitionController; public ActivityAllAppsContainerView(Context context) { @@ -778,7 +777,7 @@ public class ActivityAllAppsContainerView protected void updateHeaderScroll(int scrolledOffset) { float prog1 = Utilities.boundToRange((float) scrolledOffset / mHeaderThreshold, 0f, 1f); int headerColor = getHeaderColor(prog1); - int tabsAlpha = mHeader.getPeripheralProtectionHeight() == 0 ? 0 + int tabsAlpha = mHeader.getPeripheralProtectionHeight(/* expectedHeight */ false) == 0 ? 0 : (int) (Utilities.boundToRange( (scrolledOffset + mHeader.mSnappedScrolledY) / mHeaderThreshold, 0f, 1f) * 255); @@ -1448,15 +1447,13 @@ public class ActivityAllAppsContainerView mTmpPath.reset(); mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW); canvas.drawPath(mTmpPath, mHeaderPaint); - mTotalHeaderProtectionHeight = headerBottomWithScaleOnTablet; } } else { canvas.drawRect(0, 0, canvas.getWidth(), headerBottomWithScaleOnPhone, mHeaderPaint); - mTotalHeaderProtectionHeight = headerBottomWithScaleOnPhone; } // If tab exist (such as work profile), extend header with tab height - final int tabsHeight = headerView.getPeripheralProtectionHeight(); + final int tabsHeight = headerView.getPeripheralProtectionHeight(/* expectedHeight */ false); if (mTabsProtectionAlpha > 0 && tabsHeight != 0) { if (DEBUG_HEADER_PROTECTION) { mHeaderPaint.setColor(Color.BLUE); @@ -1482,16 +1479,19 @@ public class ActivityAllAppsContainerView right, tabBottomWithScale, mHeaderPaint); - mTotalHeaderProtectionHeight = tabBottomWithScale; } } /** - * The height of the header protection is dynamically calculated during the time of drawing the - * header. + * The height of the header protection as if the user scrolled down the app list. */ float getHeaderProtectionHeight() { - return mTotalHeaderProtectionHeight; + float headerBottom = getHeaderBottom() - getTranslationY(); + if (mUsingTabs) { + return headerBottom + mHeader.getPeripheralProtectionHeight(/* expectedHeight */ true); + } else { + return headerBottom; + } } /** @@ -1515,6 +1515,10 @@ public class ActivityAllAppsContainerView return bottom + mHeader.getTop(); } + boolean isUsingTabs() { + return mUsingTabs; + } + /** * Returns a view that denotes the visible part of all apps container view. */ diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java index a1f6ebe557..ecba23f2cc 100644 --- a/src/com/android/launcher3/allapps/FloatingHeaderView.java +++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java @@ -466,9 +466,14 @@ public class FloatingHeaderView extends LinearLayout implements } /** - * Returns visible height of FloatingHeaderView contents requiring header protection + * Returns visible height of FloatingHeaderView contents requiring header protection or the + * expected header protection height. */ - int getPeripheralProtectionHeight() { + int getPeripheralProtectionHeight(boolean expected) { + if (expected) { + return getTabLayout().getBottom() - getPaddingTop() + getPaddingBottom() + - mMaxTranslation; + } // we only want to show protection when work tab is available and header is either // collapsed or animating to/from collapsed state if (mTabsHidden || mFloatingRowsCollapsed || !mHeaderCollapsed) { diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java index be120cce75..a6a2f91513 100644 --- a/src/com/android/launcher3/allapps/PrivateProfileManager.java +++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java @@ -509,9 +509,12 @@ public class PrivateProfileManager extends UserProfileManager { if (rowToExpandToWithRespectToHeader == -1) { rowToExpandToWithRespectToHeader = currentItem.rowIndex; } + // If there are no tabs, decrease the row to scroll to by 1 since the header + // may be cut off slightly. int rowToScrollTo = (int) Math.floor((double) (mAllApps.getHeight() - psHeaderHeight - - mAllApps.getHeaderProtectionHeight()) / allAppsCellHeight); + - mAllApps.getHeaderProtectionHeight()) / allAppsCellHeight) + - (mAllApps.isUsingTabs() ? 0 : 1); int currentRowDistance = currentItem.rowIndex - rowToExpandToWithRespectToHeader; // rowToScrollTo - 1 since the item to scroll to is 0 indexed. if (currentRowDistance == rowToScrollTo - 1) { diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java index 351b921e97..9363ce81c6 100644 --- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java +++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java @@ -290,6 +290,7 @@ public class PrivateSpaceHeaderViewTest { doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); + when(mAllApps.isUsingTabs()).thenReturn(true); mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, null, privateProfileManager); mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); @@ -310,6 +311,43 @@ public class PrivateSpaceHeaderViewTest { ALL_APPS_CELL_HEIGHT)); } + @Test + public void scrollForViewToBeVisibleInContainer_withHeaderNoTabs() { + when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); + PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager); + when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED); + when(privateProfileManager.splitIntoUserInstalledAndSystemApps()) + .thenReturn(iteminfo -> iteminfo.componentName == null + || !iteminfo.componentName.getPackageName() + .equals(CAMERA_PACKAGE_NAME)); + doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any()); + doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager) + .addPrivateSpaceHeader(any()); + doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); + doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); + when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); + when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); + when(mAllApps.isUsingTabs()).thenReturn(false); + mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, + null, privateProfileManager); + mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS); + mAlphabeticalAppsList.updateItemFilter(info -> info != null + && info.user.equals(MAIN_HANDLE)); + + int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT) - 1; + int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1; + + // The number of adapterItems should be the private space apps + one main app + header. + assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1, + mAlphabeticalAppsList.getAdapterItems().size()); + assertEquals(position, + privateProfileManager.scrollForHeaderToBeVisibleInContainer( + new AllAppsRecyclerView(mContext), + mAlphabeticalAppsList.getAdapterItems(), + PS_HEADER_HEIGHT, + ALL_APPS_CELL_HEIGHT)); + } + @Test public void scrollForViewToBeVisibleInContainer_withHeaderAndLessAppRowSpace() { when(mAllAppsStore.getApps()).thenReturn(createAppInfoList()); @@ -325,6 +363,7 @@ public class PrivateSpaceHeaderViewTest { doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any()); doReturn(0).when(privateProfileManager).addSystemAppsDivider(any()); when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT); + when(mAllApps.isUsingTabs()).thenReturn(true); when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT); mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore, null, privateProfileManager);