Merge "Add logging for Onboarding Bug: 73784423" into ub-launcher3-edmonton
diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
index 0451653..a11625a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
@@ -28,7 +28,7 @@
| FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY;
public FastOverviewState(int id) {
- super(id, QuickScrubController.QUICK_SCRUB_START_DURATION, STATE_FLAGS);
+ super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index febe360..79e3c42 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -17,6 +17,8 @@
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.RecentsView.ADJACENT_SCALE;
import static com.android.quickstep.views.RecentsViewContainer.CONTENT_ALPHA;
@@ -24,12 +26,14 @@
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
+import android.view.animation.Interpolator;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PropertySetter;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsViewContainer;
@@ -69,7 +73,13 @@
PropertySetter setter = config.getPropertySetter(builder);
float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], LINEAR);
- setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1], LINEAR);
+ Interpolator transYInterpolator = LINEAR;
+ if (toState == LauncherState.FAST_OVERVIEW) {
+ transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
+ QUICK_SCRUB_TRANSLATION_Y_FACTOR);
+ }
+ setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
+ transYInterpolator);
setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
AGGRESSIVE_EASE_IN_OUT);
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index ae7de87..8398c48 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -16,8 +16,11 @@
package com.android.quickstep;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+
import android.util.Log;
import android.view.HapticFeedbackConstants;
+import android.view.animation.Interpolator;
import com.android.launcher3.Alarm;
import com.android.launcher3.BaseActivity;
@@ -37,7 +40,11 @@
*/
public class QuickScrubController implements OnAlarmListener {
- public static final int QUICK_SCRUB_START_DURATION = 210;
+ public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240;
+ public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 150;
+ // We want the translation y to finish faster than the rest of the animation.
+ public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6;
+ public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN;
/**
* Snap to a new page when crossing these thresholds. The first and last auto-advance.
@@ -168,23 +175,27 @@
public void snapToNextTaskIfAvailable() {
if (mInQuickScrub && mRecentsView.getChildCount() > 0) {
+ int duration = mStartedFromHome ? QUICK_SCRUB_FROM_HOME_START_DURATION
+ : QUICK_SCRUB_FROM_APP_START_DURATION;
int pageToGoTo = mStartedFromHome ? 0 : mRecentsView.getNextPage() + 1;
- goToPageWithHaptic(pageToGoTo, QUICK_SCRUB_START_DURATION, true /* forceHaptic */);
+ goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */,
+ QUICK_SCRUB_START_INTERPOLATOR);
}
}
private void goToPageWithHaptic(int pageToGoTo) {
- goToPageWithHaptic(pageToGoTo, -1 /* overrideDuration */, false /* forceHaptic */);
+ goToPageWithHaptic(pageToGoTo, -1 /* overrideDuration */, false /* forceHaptic */, null);
}
- private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic) {
+ private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic,
+ Interpolator interpolator) {
pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getPageCount() - 1);
boolean snappingToPage = pageToGoTo != mRecentsView.getNextPage();
if (snappingToPage) {
int duration = overrideDuration > -1 ? overrideDuration
: Math.abs(pageToGoTo - mRecentsView.getNextPage())
* QUICKSCRUB_SNAP_DURATION_PER_PAGE;
- mRecentsView.snapToPage(pageToGoTo, duration);
+ mRecentsView.snapToPage(pageToGoTo, duration, interpolator);
}
if (snappingToPage || forceHaptic) {
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 911a602..807dae8 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -17,11 +17,9 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_DURATION;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
@@ -454,7 +452,7 @@
setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
// Start the window animation without waiting for launcher.
- animateToProgress(1f, QUICK_SCRUB_START_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
+ animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR);
}
@WorkerThread
@@ -501,10 +499,7 @@
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
- Interpolator interpolator = mInteractionType == INTERACTION_QUICK_SCRUB
- ? ACCEL_2 : LINEAR;
- float interpolated = interpolator.getInterpolation(shift);
- mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, interpolated);
+ mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, shift);
// TODO: This logic is spartanic!
boolean passedThreshold = shift > 0.12f;
@@ -792,7 +787,8 @@
}
mClipAnimationHelper.offsetTarget(
firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
- mActivityControlHelper.getTranslationYForQuickScrub(mActivity));
+ mActivityControlHelper.getTranslationYForQuickScrub(mActivity),
+ QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index 14b4046..c28a6bd 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -16,7 +16,7 @@
package com.android.quickstep.util;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.SCROLL;
+import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -30,11 +30,13 @@
import android.os.Build;
import android.os.RemoteException;
import android.support.annotation.Nullable;
+import android.view.animation.Interpolator;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView;
@@ -78,6 +80,9 @@
private final RectF mTmpRectF = new RectF();
private float mTargetScale = 1f;
+ private Interpolator mInterpolator = LINEAR;
+ // We translate y slightly faster than the rest of the animation for quick scrub.
+ private Interpolator mOffsetYInterpolator = LINEAR;
// Whether to boost the opening animation target layers, or the closing
private int mBoostModeTargetLayers = -1;
@@ -134,12 +139,13 @@
RectF currentRect;
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
+ float offsetYProgress = mOffsetYInterpolator.getInterpolation(progress);
+ progress = mInterpolator.getInterpolation(progress);
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
synchronized (mTargetOffset) {
// Stay lined up with the center of the target, since it moves for quick scrub.
- currentRect.offset(mTargetOffset.x * SCROLL.getInterpolation(progress),
- mTargetOffset.y * LINEAR.getInterpolation(progress));
+ currentRect.offset(mTargetOffset.x * progress, mTargetOffset.y * offsetYProgress);
}
mClipRect.left = (int) (mSourceWindowClipInsets.left * progress);
@@ -180,11 +186,14 @@
mTaskTransformCallback = callback;
}
- public void offsetTarget(float scale, float offsetX, float offsetY) {
+ public void offsetTarget(float scale, float offsetX, float offsetY, Interpolator interpolator) {
synchronized (mTargetOffset) {
- mTargetScale = scale;
mTargetOffset.set(offsetX, offsetY);
}
+ mTargetScale = scale;
+ mInterpolator = interpolator;
+ mOffsetYInterpolator = Interpolators.clampToProgress(mInterpolator, 0,
+ QUICK_SCRUB_TRANSLATION_Y_FACTOR);
}
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ad85d9e..05793f1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -121,6 +121,8 @@
// Keeps track of the previously known visible tasks for purposes of loading/unloading task data
private final SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray();
+ private boolean mIsClearAllButtonFullyRevealed;
+
/**
* TODO: Call reloadIdNeeded in onTaskStackChanged.
*/
@@ -337,11 +339,15 @@
}
}
+ private int getScrollEnd() {
+ return mIsRtl ? 0 : mMaxScrollX;
+ }
+
private float calculateClearAllButtonAlpha() {
final int childCount = getChildCount();
if (mShowEmptyMessage || childCount == 0) return 0;
- final int scrollEnd = mIsRtl ? 0 : mMaxScrollX;
+ final int scrollEnd = getScrollEnd();
final int oldestChildScroll = getScrollForPage(childCount - 1);
return Utilities.boundToRange(
@@ -352,6 +358,7 @@
private void updateClearAllButtonAlpha() {
if (mClearAllButton != null) {
final float alpha = calculateClearAllButtonAlpha();
+ mIsClearAllButtonFullyRevealed = alpha == 1;
mClearAllButton.setAlpha(alpha * mContentAlpha);
}
}
@@ -363,9 +370,18 @@
}
@Override
+ protected void restoreScrollOnLayout() {
+ if (mIsClearAllButtonFullyRevealed) {
+ scrollAndForceFinish(getScrollEnd());
+ } else {
+ super.restoreScrollOnLayout();
+ }
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN && mTouchState == TOUCH_STATE_REST
- && mScroller.isFinished() && mClearAllButton.getAlpha() > 0) {
+ && mScroller.isFinished() && mIsClearAllButtonFullyRevealed) {
mClearAllButton.getHitRect(mTempRect);
mTempRect.offset(-getLeft(), -getTop());
if (mTempRect.contains((int) ev.getX(), (int) ev.getY())) {
@@ -829,7 +845,7 @@
removeView(taskView);
if (getChildCount() == 0) {
onAllTasksRemoved();
- } else {
+ } else if (!mIsClearAllButtonFullyRevealed) {
snapToPageImmediately(pageToSnapTo);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index af7a735..128a19e 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,7 +16,6 @@
package com.android.quickstep.views;
-import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
import android.content.Context;
@@ -52,16 +51,16 @@
private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
- public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
- new FloatProperty<TaskThumbnailView>("dimAlpha") {
+ public static final Property<TaskThumbnailView, Float> DIM_ALPHA_MULTIPLIER =
+ new FloatProperty<TaskThumbnailView>("dimAlphaMultiplier") {
@Override
- public void setValue(TaskThumbnailView thumbnail, float dimAlpha) {
- thumbnail.setDimAlpha(dimAlpha);
+ public void setValue(TaskThumbnailView thumbnail, float dimAlphaMultiplier) {
+ thumbnail.setDimAlphaMultipler(dimAlphaMultiplier);
}
@Override
public Float get(TaskThumbnailView thumbnailView) {
- return thumbnailView.mDimAlpha;
+ return thumbnailView.mDimAlphaMultiplier;
}
};
@@ -81,6 +80,7 @@
protected BitmapShader mBitmapShader;
private float mDimAlpha = 1f;
+ private float mDimAlphaMultiplier = 1f;
public TaskThumbnailView(Context context) {
this(context, null);
@@ -128,6 +128,11 @@
updateThumbnailPaintFilter();
}
+ public void setDimAlphaMultipler(float dimAlphaMultipler) {
+ mDimAlphaMultiplier = dimAlphaMultipler;
+ setDimAlpha(mDimAlpha);
+ }
+
/**
* Sets the alpha of the dim layer on top of this view.
*
@@ -191,7 +196,7 @@
}
private void updateThumbnailPaintFilter() {
- int mul = (int) ((1 - mDimAlpha) * 255);
+ int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
if (mBitmapShader != null) {
LightingColorFilter filter = getLightingColorFilter(mul);
mPaint.setColorFilter(filter);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 4f447b1..4b2ca45 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -17,7 +17,7 @@
package com.android.quickstep.views;
import static android.widget.Toast.LENGTH_SHORT;
-import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
+import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA_MULTIPLIER;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -78,6 +78,7 @@
private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
public static final long SCALE_ICON_DURATION = 120;
+ private static final long DIM_ANIM_DURATION = 700;
public static final Property<TaskView, Float> ZOOM_SCALE =
new FloatProperty<TaskView>("zoomScale") {
@@ -97,7 +98,6 @@
private IconView mIconView;
private float mCurveScale;
private float mZoomScale;
- private float mCurveDimAlpha;
private Animator mDimAlphaAnim;
public TaskView(Context context) {
@@ -200,8 +200,9 @@
public void animateIconToScaleAndDim(float scale) {
mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start();
- mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA, scale * mCurveDimAlpha);
- mDimAlphaAnim.setDuration(SCALE_ICON_DURATION);
+ mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA_MULTIPLIER, 1 - scale,
+ scale);
+ mDimAlphaAnim.setDuration(DIM_ANIM_DURATION);
mDimAlphaAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -218,7 +219,7 @@
if (mDimAlphaAnim != null) {
mDimAlphaAnim.cancel();
}
- mSnapshotView.setDimAlpha(iconScale * mCurveDimAlpha);
+ mSnapshotView.setDimAlphaMultipler(iconScale);
}
public void resetVisualProperties() {
@@ -235,11 +236,7 @@
float curveInterpolation =
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
- mCurveDimAlpha = curveInterpolation * MAX_PAGE_SCRIM_ALPHA;
- if (mDimAlphaAnim == null && mIconView.getScaleX() > 0) {
- mSnapshotView.setDimAlpha(mCurveDimAlpha);
- }
-
+ mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation));
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 990132d..eb816c5 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -27,6 +27,7 @@
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -44,6 +45,7 @@
import android.widget.ScrollView;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.util.Thunk;
@@ -238,6 +240,12 @@
return index;
}
+ protected void scrollAndForceFinish(int scrollX) {
+ scrollTo(scrollX, 0);
+ mScroller.setFinalX(scrollX);
+ forceFinishScroller(true);
+ }
+
/**
* Updates the scroll of the current page immediately to its final scroll position. We use this
* in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
@@ -249,9 +257,7 @@
if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
newX = getScrollForPage(mCurrentPage);
}
- scrollTo(newX, 0);
- mScroller.setFinalX(newX);
- forceFinishScroller(true);
+ scrollAndForceFinish(newX);
}
private void abortScrollerAnimation(boolean resetNextPage) {
@@ -538,6 +544,10 @@
setMeasuredDimension(widthSize, heightSize);
}
+ protected void restoreScrollOnLayout() {
+ setCurrentPage(getNextPage());
+ }
+
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
@@ -589,7 +599,7 @@
}
if (mScroller.isFinished() && pageScrollChanged) {
- setCurrentPage(getNextPage());
+ restoreScrollOnLayout();
}
}
@@ -1421,7 +1431,7 @@
return snapToPage(whichPage, duration, false, null);
}
- protected boolean snapToPage(int whichPage, int duration, TimeInterpolator interpolator) {
+ public boolean snapToPage(int whichPage, int duration, TimeInterpolator interpolator) {
return snapToPage(whichPage, duration, false, interpolator);
}
@@ -1440,6 +1450,12 @@
protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate,
TimeInterpolator interpolator) {
+
+ if (FeatureFlags.IS_DOGFOOD_BUILD) {
+ duration *= Settings.System.getFloat(getContext().getContentResolver(),
+ Settings.System.WINDOW_ANIMATION_SCALE, 1);
+ }
+
whichPage = validateNewPage(whichPage);
mNextPage = whichPage;
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 0d388fe..8374f98 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -115,4 +115,24 @@
public static Interpolator scrollInterpolatorForVelocity(float velocity) {
return Math.abs(velocity) > FAST_FLING_PX_MS ? SCROLL : SCROLL_CUBIC;
}
+
+ /**
+ * Runs the given interpolator such that the entire progress is set between the given bounds.
+ * That is, we set the interpolation to 0 until lowerBound and reach 1 by upperBound.
+ */
+ public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
+ float upperBound) {
+ if (upperBound <= lowerBound) {
+ throw new IllegalArgumentException("lowerBound must be less than upperBound");
+ }
+ return t -> {
+ if (t < lowerBound) {
+ return 0;
+ }
+ if (t > upperBound) {
+ return 1;
+ }
+ return interpolator.getInterpolation((t - lowerBound) / (upperBound - lowerBound));
+ };
+ }
}
\ No newline at end of file