Merge "Implement overshoot and squish motion in all apps open" into sc-dev am: afd470fc69

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

Change-Id: Iba165d235e9bdefda3cf1e41b8fd037f02531524
This commit is contained in:
Hyunyoung Song
2021-05-12 18:08:36 +00:00
committed by Automerger Merge Worker
5 changed files with 71 additions and 18 deletions

View File

@@ -84,7 +84,7 @@
<dimen name="fastscroll_end_margin">-26dp</dimen>
<!-- All Apps -->
<dimen name="all_apps_open_vertical_translate">300dp</dimen>
<dimen name="all_apps_open_vertical_translate">320dp</dimen>
<dimen name="all_apps_search_bar_field_height">48dp</dimen>
<dimen name="all_apps_search_bar_bottom_padding">30dp</dimen>
<dimen name="all_apps_empty_search_message_top_offset">40dp</dimen>

View File

@@ -45,6 +45,7 @@ import android.view.WindowInsets;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.ColorUtils;
import androidx.core.os.BuildCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
@@ -79,10 +80,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
ScrimView.ScrimDrawingController {
private static final float FLING_VELOCITY_MULTIPLIER = 1000f;
public static final float PULL_MULTIPLIER = .02f;
public static final float FLING_VELOCITY_MULTIPLIER = 2000f;
// Starts the springs after at least 25% of the animation has passed.
private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
public static final float FLING_ANIMATION_THRESHOLD = 0.25f;
private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -100,6 +102,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
private AllAppsPagedView mViewPager;
protected FloatingHeaderView mHeader;
private float mHeaderTop;
private WorkModeSwitch mWorkModeSwitch;
@@ -530,7 +533,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
return view.getGlobalVisibleRect(new Rect());
}
// Used by tests only
@VisibleForTesting
public boolean isPersonalTabVisible() {
return isDescendantViewVisible(R.id.tab_personal);
}
@@ -582,6 +585,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
mAH[i].padding.top = padding;
mAH[i].applyPadding();
}
mHeaderTop = mHeader.getTop();
}
public void setLastSearchQuery(String query) {
@@ -636,14 +640,42 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
public void onAnimationUpdate(ValueAnimator valueAnimator) {
if (shouldSpring
&& valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
absorbSwipeUpVelocity(Math.abs(
Math.round(velocity * FLING_VELOCITY_MULTIPLIER)));
absorbSwipeUpVelocity(Math.max(100, Math.abs(
Math.round(velocity * FLING_VELOCITY_MULTIPLIER))));
// calculate the velocity of using the not user controlled interpolator
// of when the container reach the end.
shouldSpring = false;
}
}
});
}
public void onPull(float deltaDistance, float displacement) {
absorbPullDeltaDistance(PULL_MULTIPLIER * deltaDistance,
PULL_MULTIPLIER * displacement);
// ideally, this should be done using EdgeEffect.onPush to create squish effect.
// However, until such method is available, launcher to simulate the onPush method.
mHeader.setTranslationY(-.5f * mHeaderTop * deltaDistance);
getRecyclerViewContainer().setTranslationY(-mHeaderTop * deltaDistance);
}
public void onRelease() {
ValueAnimator anim1 = ValueAnimator.ofFloat(1f, 0f);
final float floatingHeaderHeight = getFloatingHeaderView().getTranslationY();
final float recyclerViewHeight = getRecyclerViewContainer().getTranslationY();
anim1.setDuration(200);
anim1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
getFloatingHeaderView().setTranslationY(
((float) valueAnimator.getAnimatedValue()) * floatingHeaderHeight);
getRecyclerViewContainer().setTranslationY(
((float) valueAnimator.getAnimatedValue()) * recyclerViewHeight);
}
});
anim1.start();
super.onRelease();
}
@Override
public void getDrawingRect(Rect outRect) {
super.getDrawingRect(outRect);

View File

@@ -17,10 +17,7 @@ package com.android.launcher3.allapps;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
@@ -158,9 +155,8 @@ public class AllAppsTransitionController
return;
}
Interpolator interpolator = toState.equals(ALL_APPS)
? (config.userControlled ? ACCEL_2 : ACCEL_0_75) :
(config.userControlled ? DEACCEL_2 : DEACCEL);
// need to decide depending on the release velocity
Interpolator interpolator = (config.userControlled ? LINEAR : DEACCEL_1_7);
Animator anim = createSpringAnimation(mProgress, targetProgress);
anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));

View File

@@ -56,9 +56,8 @@ public abstract class AbstractStateChangeTouchController
protected final AnimatorListener mClearStateOnCancelListener =
newCancelListener(this::clearState);
private final FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private boolean mNoIntercept;
private boolean mIsLogContainerSet;
protected int mStartContainerType;
protected LauncherState mStartState;
@@ -67,12 +66,14 @@ public abstract class AbstractStateChangeTouchController
protected AnimatorPlaybackController mCurrentAnimation;
protected boolean mGoingBetweenStates = true;
private boolean mNoIntercept;
private boolean mIsLogContainerSet;
private float mStartProgress;
// Ratio of transition process [0, 1] to drag displacement (px)
private float mProgressMultiplier;
private float mDisplacementShift;
private boolean mCanBlockFling;
private final FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private boolean mAllAppsOvershootStarted;
public AbstractStateChangeTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
mLauncher = l;
@@ -216,8 +217,15 @@ public abstract class AbstractStateChangeTouchController
mFlingBlockCheck.blockFling();
}
}
if (mToState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
mAllAppsOvershootStarted = true;
// 1f, value when all apps container hit the top
mLauncher.getAppsView().onPull(progress - 1f, progress - 1f);
}
} else {
mFlingBlockCheck.onEvent();
}
return true;
@@ -325,8 +333,15 @@ public abstract class AbstractStateChangeTouchController
anim.setFloatValues(startProgress, endProgress);
updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
mCurrentAnimation.dispatchOnStart();
if (fling && targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
if (targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
if (mAllAppsOvershootStarted) {
mLauncher.getAppsView().onRelease();
mAllAppsOvershootStarted = false;
} else {
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
}
}
anim.start();
}

View File

@@ -32,6 +32,7 @@ import com.android.launcher3.Utilities;
*/
public class SpringRelativeLayout extends RelativeLayout {
// fixed edge at the time force is applied
private final EdgeEffect mEdgeGlowTop;
private final EdgeEffect mEdgeGlowBottom;
@@ -87,6 +88,15 @@ public class SpringRelativeLayout extends RelativeLayout {
invalidate();
}
protected void absorbPullDeltaDistance(float deltaDistance, float displacement) {
mEdgeGlowBottom.onPull(deltaDistance, displacement);
invalidate();
}
protected void onRelease() {
mEdgeGlowBottom.onRelease();
}
public EdgeEffectFactory createEdgeEffectFactory() {
return new ProxyEdgeEffectFactory();
}