Merge "[Predictive Back] Widget to home polish: show extra rows at bottom during animation" into tm-qpr-dev
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index a5f72ef..b76eef7 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -18,7 +18,6 @@
android:id="@+id/widgets_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/bg_rounded_corner_bottom_sheet"
android:paddingTop="@dimen/bottom_sheet_handle_margin"
android:orientation="vertical">
<View
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index e3f1fca..e31bf7a 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -25,7 +25,6 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/bg_widgets_full_sheet"
android:focusable="true"
android:importantForAccessibility="no">
diff --git a/res/layout/widgets_full_sheet_large_screen.xml b/res/layout/widgets_full_sheet_large_screen.xml
index 3dbe6f5..1c0037d 100644
--- a/res/layout/widgets_full_sheet_large_screen.xml
+++ b/res/layout/widgets_full_sheet_large_screen.xml
@@ -24,7 +24,6 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/bg_widgets_full_sheet"
android:focusable="true"
android:importantForAccessibility="no">
diff --git a/res/layout/widgets_full_sheet_paged_view.xml b/res/layout/widgets_full_sheet_paged_view.xml
index 2819b99..b02e3e3 100644
--- a/res/layout/widgets_full_sheet_paged_view.xml
+++ b/res/layout/widgets_full_sheet_paged_view.xml
@@ -47,6 +47,7 @@
android:layout_height="wrap_content"
android:layout_below="@id/collapse_handle"
android:paddingBottom="0dp"
+ android:clipToOutline="true"
android:orientation="vertical">
<TextView
diff --git a/res/layout/widgets_full_sheet_paged_view_large_screen.xml b/res/layout/widgets_full_sheet_paged_view_large_screen.xml
index 6634345..edee352 100644
--- a/res/layout/widgets_full_sheet_paged_view_large_screen.xml
+++ b/res/layout/widgets_full_sheet_paged_view_large_screen.xml
@@ -53,6 +53,7 @@
android:id="@+id/search_and_recommendations_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipToOutline="true"
android:orientation="vertical">
<FrameLayout
diff --git a/res/layout/widgets_full_sheet_recyclerview.xml b/res/layout/widgets_full_sheet_recyclerview.xml
index 2291943..366d2d2 100644
--- a/res/layout/widgets_full_sheet_recyclerview.xml
+++ b/res/layout/widgets_full_sheet_recyclerview.xml
@@ -31,6 +31,7 @@
android:layout_below="@id/collapse_handle"
android:paddingBottom="16dp"
android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
+ android:clipToOutline="true"
android:orientation="vertical">
<TextView
diff --git a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml b/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
index 212cd55..c6a4f62 100644
--- a/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
+++ b/res/layout/widgets_full_sheet_recyclerview_large_screen.xml
@@ -38,6 +38,7 @@
android:id="@+id/search_and_recommendations_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipToOutline="true"
android:orientation="vertical">
<FrameLayout
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 7641728..14e3fa6 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -16,10 +16,10 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
-import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_COUNT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
+import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -526,7 +526,7 @@
public void getOutline(View view, Outline outline) {
@Px final int bottomOffsetPx =
(int) (ActivityAllAppsContainerView.this.getMeasuredHeight()
- * SWIPE_ALL_APPS_TO_HOME_MIN_SCALE);
+ * PREDICTIVE_BACK_MIN_SCALE);
outline.setRect(
0,
0,
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 866932a..df383bf 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -21,7 +21,6 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import androidx.annotation.Px;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
@@ -146,19 +145,6 @@
}
/**
- * We need to extend all apps' RecyclerView's bottom by 5% of view height to ensure extra
- * roll(s) of app icons is rendered at the bottom, so that they can fill the bottom gap
- * created during predictive back's scale animation from all apps to home.
- */
- @Override
- protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
- super.calculateExtraLayoutSpace(state, extraLayoutSpace);
- @Px int extraSpacePx = (int) (getHeight()
- * (1 - AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) / 2);
- extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
- }
-
- /**
* Returns the number of rows before {@param adapterPosition}, including this position
* which should not be counted towards the collection info.
*/
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index b618724..92c017c 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -61,6 +61,7 @@
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.ScrollableLayoutManager;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.ScrimView;
@@ -79,8 +80,7 @@
implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
// This constant should match the second derivative of the animator interpolator.
public static final float INTERP_COEFF = 1.7f;
- public static final float SWIPE_ALL_APPS_TO_HOME_MIN_SCALE = 0.9f;
- private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;
+ public static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;
private static final float NAV_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.1f;
private static final float SWIPE_DRAG_COMMIT_THRESHOLD =
@@ -280,8 +280,9 @@
float deceleratedProgress =
Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(backProgress);
- float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
- + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
+ float scaleProgress = ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE
+ + (1 - ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE)
+ * (1 - deceleratedProgress);
mAllAppScale.updateValue(scaleProgress);
}
diff --git a/src/com/android/launcher3/util/ScrollableLayoutManager.java b/src/com/android/launcher3/util/ScrollableLayoutManager.java
index 9bc4ddc..cb6ecaa 100644
--- a/src/com/android/launcher3/util/ScrollableLayoutManager.java
+++ b/src/com/android/launcher3/util/ScrollableLayoutManager.java
@@ -20,6 +20,7 @@
import android.view.View;
import androidx.annotation.NonNull;
+import androidx.annotation.Px;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
@@ -31,6 +32,10 @@
*/
public class ScrollableLayoutManager extends GridLayoutManager {
+ public static final float PREDICTIVE_BACK_MIN_SCALE = 0.9f;
+ private static final float EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT =
+ (1 - PREDICTIVE_BACK_MIN_SCALE) / 2;
+
// keyed on item type
protected final SparseIntArray mCachedSizes = new SparseIntArray();
@@ -111,6 +116,13 @@
return adapter == null ? 0 : getItemsHeight(adapter, adapter.getItemCount());
}
+ @Override
+ protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
+ super.calculateExtraLayoutSpace(state, extraLayoutSpace);
+ @Px int extraSpacePx = (int) (getHeight() * EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT);
+ extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
+ }
+
/**
* Returns the sum of the height, in pixels, of this list adapter's items from index
* 0 (inclusive) until {@code untilIndex} (exclusive). If untilIndex is same as the itemCount,
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index f73347a..e2f1c04 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,15 +17,20 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
+import static com.android.launcher3.allapps.AllAppsTransitionController.REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Property;
import android.view.MotionEvent;
@@ -33,10 +38,13 @@
import android.view.ViewGroup;
import android.view.animation.Interpolator;
+import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
@@ -85,6 +93,10 @@
protected @Nullable OnCloseListener mOnCloseBeginListener;
protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
+ private final AnimatedFloat mSlidInViewScale = new AnimatedFloat(this::onScaleProgressChanged);
+ private boolean mIsBackProgressing;
+ @Nullable private Drawable mContentBackground;
+
public AbstractSlideInView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mActivityContext = ActivityContext.lookupContext(context);
@@ -105,6 +117,10 @@
mColorScrim = scrimColor != -1 ? createColorScrim(context, scrimColor) : null;
}
+ protected void setContentBackground(Drawable drawable) {
+ mContentBackground = drawable;
+ }
+
protected void attachToContainer() {
if (mColorScrim != null) {
getPopupContainer().addView(mColorScrim);
@@ -132,6 +148,7 @@
if (mColorScrim != null) {
mColorScrim.setAlpha(1 - mTranslationShift);
}
+ invalidate();
}
@Override
@@ -161,6 +178,68 @@
return true;
}
+ @Override
+ public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
+ super.onBackProgressed(progress);
+ float deceleratedProgress =
+ Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
+ mIsBackProgressing = progress > 0f;
+ mSlidInViewScale.updateValue(PREDICTIVE_BACK_MIN_SCALE
+ + (1 - PREDICTIVE_BACK_MIN_SCALE) * (1 - deceleratedProgress));
+ }
+
+ private void onScaleProgressChanged() {
+ float scaleProgress = mSlidInViewScale.value;
+ SCALE_PROPERTY.set(this, scaleProgress);
+ setClipChildren(!mIsBackProgressing);
+ mContent.setClipChildren(!mIsBackProgressing);
+ invalidate();
+ }
+
+ @Override
+ public void onBackInvoked() {
+ super.onBackInvoked();
+ animateSlideInViewToNoScale();
+ }
+
+ @Override
+ public void onBackCancelled() {
+ super.onBackCancelled();
+ animateSlideInViewToNoScale();
+ }
+
+ protected void animateSlideInViewToNoScale() {
+ mSlidInViewScale.animateToValue(1f)
+ .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
+ .start();
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ drawScaledBackground(canvas);
+ super.dispatchDraw(canvas);
+ }
+
+ /** Draw scaled background during predictive back animation. */
+ protected void drawScaledBackground(Canvas canvas) {
+ if (mContentBackground == null) {
+ return;
+ }
+ mContentBackground.setBounds(
+ mContent.getLeft(),
+ mContent.getTop() + (int) mContent.getTranslationY(),
+ mContent.getRight(),
+ mContent.getBottom() + (mIsBackProgressing ? getBottomOffsetPx() : 0));
+ mContentBackground.draw(canvas);
+ }
+
+ /** Return extra space revealed during predictive back animation. */
+ @Px
+ protected int getBottomOffsetPx() {
+ return (int) (getMeasuredHeight()
+ * (1 - PREDICTIVE_BACK_MIN_SCALE) / 2);
+ }
+
/**
* Returns {@code true} if the touch event is over the visible area of the bottom sheet.
*
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index bf521cc..4099302 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -113,6 +113,7 @@
}
mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
R.dimen.widget_cell_horizontal_padding);
+ setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index 2ce400e..66e3a43 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -17,9 +17,7 @@
import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.allapps.AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE;
import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
@@ -31,6 +29,7 @@
import android.content.pm.LauncherApps;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Outline;
import android.graphics.Rect;
import android.os.Process;
import android.os.UserHandle;
@@ -42,6 +41,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -62,7 +62,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.model.UserManagerState;
@@ -170,6 +169,18 @@
}
};
+ private final ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(
+ 0,
+ 0,
+ view.getMeasuredWidth(),
+ view.getMeasuredHeight() + getBottomOffsetPx()
+ );
+ }
+ };
+
private final int mTabsHeight;
private final int mWidgetSheetContentHorizontalPadding;
@@ -195,6 +206,8 @@
private int mOrientation;
private @Nullable WidgetsRecyclerView mCurrentTouchEventRecyclerView;
+ private RecyclerViewFastScroller mFastScroller;
+
public WidgetsFullSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
DeviceProfile dp = Launcher.getLauncher(context).getDeviceProfile();
@@ -213,6 +226,7 @@
mUserManagerState.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
+ setContentBackground(getContext().getDrawable(R.drawable.bg_widgets_full_sheet));
}
public WidgetsFullSheet(Context context, AttributeSet attrs) {
@@ -224,6 +238,9 @@
super.onFinishInflate();
mContent = findViewById(R.id.container);
+ mContent.setOutlineProvider(mViewOutlineProvider);
+ mContent.setClipToOutline(true);
+
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
int contentLayoutRes = mHasWorkProfile ? R.layout.widgets_full_sheet_paged_view
: R.layout.widgets_full_sheet_recyclerview;
@@ -233,14 +250,17 @@
}
layoutInflater.inflate(contentLayoutRes, mContent, true);
- RecyclerViewFastScroller fastScroller = findViewById(R.id.fast_scroller);
+ mFastScroller = findViewById(R.id.fast_scroller);
if (mIsTwoPane) {
- fastScroller.setVisibility(GONE);
+ mFastScroller.setVisibility(GONE);
}
mAdapters.get(AdapterHolder.PRIMARY).setup(findViewById(R.id.primary_widgets_list_view));
mAdapters.get(AdapterHolder.SEARCH).setup(findViewById(R.id.search_widgets_list_view));
if (mHasWorkProfile) {
mViewPager = findViewById(R.id.widgets_view_pager);
+ mViewPager.setOutlineProvider(mViewOutlineProvider);
+ mViewPager.setClipToOutline(true);
+ mViewPager.setClipChildren(false);
mViewPager.initParentViews(this);
mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.PRIMARY);
@@ -349,11 +369,8 @@
@Override
public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
- float deceleratedProgress =
- Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
- float scaleProgress = SWIPE_ALL_APPS_TO_HOME_MIN_SCALE
- + (1 - SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) * (1 - deceleratedProgress);
- SCALE_PROPERTY.set(this, scaleProgress);
+ super.onBackProgressed(progress);
+ mFastScroller.setVisibility(progress > 0 ? View.INVISIBLE : View.VISIBLE);
}
private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
@@ -859,6 +876,7 @@
public void onBackInvoked() {
if (mIsInSearchMode) {
mSearchBar.reset();
+ animateSlideInViewToNoScale();
} else {
super.onBackInvoked();
}
@@ -1003,6 +1021,9 @@
void setup(WidgetsRecyclerView recyclerView) {
mWidgetsRecyclerView = recyclerView;
+ mWidgetsRecyclerView.setOutlineProvider(mViewOutlineProvider);
+ mWidgetsRecyclerView.setClipToOutline(true);
+ mWidgetsRecyclerView.setClipChildren(false);
mWidgetsRecyclerView.setAdapter(mWidgetsListAdapter);
mWidgetsRecyclerView.setItemAnimator(mWidgetsListItemAnimator);
mWidgetsRecyclerView.setHeaderViewDimensionsProvider(WidgetsFullSheet.this);