Merge "[Predictive Back] Widget to home polish: show extra rows at bottom during animation" into tm-qpr-dev am: 56ebfc4900

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/21390394

Change-Id: Ieae318ba634c55b7081559f78236446de3980792
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Fengjiang Li
2023-02-16 20:08:22 +00:00
committed by Automerger Merge Worker
14 changed files with 134 additions and 33 deletions

View File

@@ -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

View File

@@ -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">

View File

@@ -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">

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 class ActivityAllAppsContainerView<T extends Context & ActivityContext>
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,

View File

@@ -21,7 +21,6 @@ import android.view.View;
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;
@@ -145,19 +144,6 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
cic.isSelected()));
}
/**
* 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.

View File

@@ -61,6 +61,7 @@ import com.android.launcher3.touch.AllAppsSwipeController;
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 @@ public class AllAppsTransitionController
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 @@ public class AllAppsTransitionController
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);
}

View File

@@ -20,6 +20,7 @@ import android.util.SparseIntArray;
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 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
*/
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 @@ public class ScrollableLayoutManager extends GridLayoutManager {
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,

View File

@@ -17,15 +17,20 @@ package com.android.launcher3.views;
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.View;
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 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
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 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
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 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
if (mColorScrim != null) {
mColorScrim.setAlpha(1 - mTranslationShift);
}
invalidate();
}
@Override
@@ -161,6 +178,68 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
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.
*

View File

@@ -113,6 +113,7 @@ public class WidgetsBottomSheet extends BaseWidgetSheet {
}
mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
R.dimen.widget_cell_horizontal_padding);
setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
}
@Override

View File

@@ -17,9 +17,7 @@ package com.android.launcher3.widget.picker;
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.Context;
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.LayoutInflater;
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.Launcher;
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
}
};
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
}
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 @@ public class WidgetsFullSheet extends BaseWidgetSheet
@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 class WidgetsFullSheet extends BaseWidgetSheet
public void onBackInvoked() {
if (mIsInSearchMode) {
mSearchBar.reset();
animateSlideInViewToNoScale();
} else {
super.onBackInvoked();
}
@@ -1003,6 +1021,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet
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);