[automerger] Various quickscrub fixes am: 9bb8ffb5e3
am: c7bf48338c
Change-Id: I2ed6d0318a36148bf177108d3d2c21506644d33f
This commit is contained in:
commit
1d9a44748a
|
@ -46,6 +46,7 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherInitListener;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
|
@ -82,7 +83,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
|||
void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
|
||||
boolean activityVisible);
|
||||
|
||||
float getTranslationYForQuickScrub(T activity);
|
||||
float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
|
||||
Context context);
|
||||
|
||||
void executeOnWindowAvailable(T activity, Runnable action);
|
||||
|
||||
|
@ -151,10 +153,15 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public float getTranslationYForQuickScrub(Launcher activity) {
|
||||
LauncherRecentsView recentsView = activity.getOverviewPanel();
|
||||
return recentsView.computeTranslationYForFactor(
|
||||
FastOverviewState.OVERVIEW_TRANSLATION_FACTOR);
|
||||
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
|
||||
Context context) {
|
||||
// The padding calculations are exactly same as that of RecentsView.setInsets
|
||||
int topMargin = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
|
||||
int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
|
||||
int paddingBottom = dp.availableHeightPx + dp.getInsets().top - targetRect.rect.bottom;
|
||||
|
||||
return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -380,7 +387,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public float getTranslationYForQuickScrub(RecentsActivity activity) {
|
||||
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
|
||||
Context context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,16 @@ public class DeferredTouchConsumer implements TouchConsumer {
|
|||
mTarget.onQuickScrubProgress(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickStep(MotionEvent ev) {
|
||||
mTarget.onQuickStep(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(int command) {
|
||||
mTarget.onCommand(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preProcessMotionEvent(MotionEvent ev) {
|
||||
mVelocityTracker.addMovement(ev);
|
||||
|
@ -92,6 +102,11 @@ public class DeferredTouchConsumer implements TouchConsumer {
|
|||
return target == null ? true : target.deferNextEventToMainThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowOverviewFromAltTab() {
|
||||
mTarget.onShowOverviewFromAltTab();
|
||||
}
|
||||
|
||||
public interface DeferredTouchProvider {
|
||||
|
||||
TouchConsumer createTouchConsumer(VelocityTracker tracker);
|
||||
|
|
|
@ -55,6 +55,8 @@ public class MotionEventQueue {
|
|||
ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_QUICK_STEP =
|
||||
ACTION_VIRTUAL | (7 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_COMMAND =
|
||||
ACTION_VIRTUAL | (8 << ACTION_POINTER_INDEX_SHIFT);
|
||||
|
||||
private final EventArray mEmptyArray = new EventArray();
|
||||
private final Object mExecutionLock = new Object();
|
||||
|
@ -165,6 +167,9 @@ public class MotionEventQueue {
|
|||
case ACTION_QUICK_STEP:
|
||||
mConsumer.onQuickStep(event);
|
||||
break;
|
||||
case ACTION_COMMAND:
|
||||
mConsumer.onCommand(event.getSource());
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Invalid virtual event: " + event.getAction());
|
||||
}
|
||||
|
@ -222,6 +227,12 @@ public class MotionEventQueue {
|
|||
queueVirtualAction(ACTION_DEFER_INIT, 0);
|
||||
}
|
||||
|
||||
public void onCommand(int command) {
|
||||
MotionEvent ev = MotionEvent.obtain(0, 0, ACTION_COMMAND, 0, 0, 0);
|
||||
ev.setSource(command);
|
||||
queueNoPreProcess(ev);
|
||||
}
|
||||
|
||||
public TouchConsumer getConsumer() {
|
||||
return mConsumer;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -69,6 +70,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
|||
|
||||
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
|
||||
|
||||
private final SparseArray<RecentsAnimationState> mAnimationStates = new SparseArray<>();
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final RecentsModel mRecentsModel;
|
||||
private final Intent mHomeIntent;
|
||||
|
@ -212,8 +214,9 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
|||
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
// Create the shared handler
|
||||
RecentsAnimationState animationState = new RecentsAnimationState();
|
||||
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
|
||||
mRunningTask, this, touchTimeMs, mActivityControlHelper);
|
||||
animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper);
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.loadTasks(mRunningTask.id, null);
|
||||
|
@ -237,31 +240,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
|||
public void onHandleAssistData(Bundle bundle) {
|
||||
mRecentsModel.preloadAssistData(mRunningTask.id, bundle);
|
||||
}
|
||||
},
|
||||
new RecentsAnimationListener() {
|
||||
public void onAnimationStart(
|
||||
RecentsAnimationControllerCompat controller,
|
||||
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
if (mInteractionHandler == handler) {
|
||||
TraceHelper.partitionSection("RecentsController", "Received");
|
||||
handler.onRecentsAnimationStart(controller,
|
||||
new RemoteAnimationTargetSet(apps, MODE_CLOSING),
|
||||
homeContentInsets, minimizedHomeBounds);
|
||||
} else {
|
||||
TraceHelper.endSection("RecentsController", "Finishing no handler");
|
||||
controller.finish(false /* toHome */);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAnimationCanceled() {
|
||||
TraceHelper.endSection("RecentsController",
|
||||
"Cancelled: " + mInteractionHandler);
|
||||
if (mInteractionHandler == handler) {
|
||||
handler.onRecentsAnimationCanceled();
|
||||
}
|
||||
}
|
||||
}, null, null);
|
||||
}, animationState, null, null);
|
||||
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
startActivity.run();
|
||||
|
@ -277,6 +256,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(int command) {
|
||||
RecentsAnimationState state = mAnimationStates.get(command);
|
||||
if (state != null) {
|
||||
state.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the gesture has ended. Does not correlate to the completion of the interaction as
|
||||
* the animation can still be running.
|
||||
|
@ -398,4 +385,55 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
|||
// TODO: Consider also check if the eventQueue is using mainThread of not.
|
||||
return mInteractionHandler != null;
|
||||
}
|
||||
|
||||
private class RecentsAnimationState implements RecentsAnimationListener {
|
||||
|
||||
private final int id;
|
||||
|
||||
private RecentsAnimationControllerCompat mController;
|
||||
private RemoteAnimationTargetSet mTargets;
|
||||
private Rect mHomeContentInsets;
|
||||
private Rect mMinimizedHomeBounds;
|
||||
private boolean mCancelled;
|
||||
|
||||
public RecentsAnimationState() {
|
||||
id = mAnimationStates.size();
|
||||
mAnimationStates.put(id, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
RecentsAnimationControllerCompat controller,
|
||||
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
mController = controller;
|
||||
mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING);
|
||||
mHomeContentInsets = homeContentInsets;
|
||||
mMinimizedHomeBounds = minimizedHomeBounds;
|
||||
mEventQueue.onCommand(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled() {
|
||||
mCancelled = true;
|
||||
mEventQueue.onCommand(id);
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
if (mInteractionHandler == null || mInteractionHandler.id != id) {
|
||||
if (!mCancelled && mController != null) {
|
||||
TraceHelper.endSection("RecentsController", "Finishing no handler");
|
||||
mController.finish(false /* toHome */);
|
||||
}
|
||||
} else if (mCancelled) {
|
||||
TraceHelper.endSection("RecentsController",
|
||||
"Cancelled: " + mInteractionHandler);
|
||||
mInteractionHandler.onRecentsAnimationCanceled();
|
||||
} else {
|
||||
TraceHelper.partitionSection("RecentsController", "Received");
|
||||
mInteractionHandler.onRecentsAnimationStart(mController, mTargets,
|
||||
mHomeContentInsets, mMinimizedHomeBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import com.android.launcher3.util.TraceHelper;
|
|||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.quickstep.util.RemoteAnimationTargetSet;
|
||||
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
|
@ -27,6 +29,10 @@ import java.util.concurrent.ExecutorService;
|
|||
*/
|
||||
public class RecentsAnimationWrapper {
|
||||
|
||||
// A list of callbacks to run when we receive the recents animation target. There are different
|
||||
// than the state callbacks as these run on the current worker thread.
|
||||
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
|
||||
|
||||
public RemoteAnimationTargetSet targetSet;
|
||||
|
||||
private RecentsAnimationControllerCompat mController;
|
||||
|
@ -46,6 +52,21 @@ public class RecentsAnimationWrapper {
|
|||
if (mInputConsumerEnabled) {
|
||||
enableInputConsumer();
|
||||
}
|
||||
|
||||
if (!mCallbacks.isEmpty()) {
|
||||
for (Runnable action : new ArrayList<>(mCallbacks)) {
|
||||
action.run();
|
||||
}
|
||||
mCallbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void runOnInit(Runnable action) {
|
||||
if (targetSet == null) {
|
||||
mCallbacks.add(action);
|
||||
} else {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,6 +48,8 @@ public interface TouchConsumer extends Consumer<MotionEvent> {
|
|||
|
||||
default void onQuickStep(MotionEvent ev) { }
|
||||
|
||||
default void onCommand(int command) { }
|
||||
|
||||
/**
|
||||
* Called on the binder thread to allow the consumer to process the motion event before it is
|
||||
* posted on a handler thread.
|
||||
|
|
|
@ -29,6 +29,7 @@ import android.animation.ObjectAnimator;
|
|||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
|
@ -36,6 +37,7 @@ import android.os.Build;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.AnyThread;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
@ -51,6 +53,7 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
|
@ -65,11 +68,12 @@ import com.android.quickstep.ActivityControlHelper.AnimationFactory;
|
|||
import com.android.quickstep.ActivityControlHelper.LayoutListener;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
import com.android.quickstep.util.ClipAnimationHelper;
|
||||
import com.android.quickstep.util.TransformedRect;
|
||||
import com.android.quickstep.util.RemoteAnimationTargetSet;
|
||||
import com.android.quickstep.util.TransformedRect;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
|
||||
|
@ -167,6 +171,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
|
||||
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
// An increasing identifier per single instance of OtherActivityTouchConsumer. Generally one
|
||||
// instance of OtherActivityTouchConsumer will only have one swipe handle, but sometimes we can
|
||||
// end up with multiple handlers if we get recents command in the middle of a swipe gesture.
|
||||
// This is used to match the corresponding activity manager callbacks in
|
||||
// OtherActivityTouchConsumer
|
||||
public final int id;
|
||||
private final Context mContext;
|
||||
private final ActivityControlHelper<T> mActivityControlHelper;
|
||||
private final ActivityInitListener mActivityInitListener;
|
||||
|
@ -199,6 +209,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
InputConsumerController.getRecentsAnimationInputConsumer();
|
||||
|
||||
private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
|
||||
|
||||
private final long mTouchTimeMs;
|
||||
private long mLauncherFrameDrawnTime;
|
||||
|
||||
|
@ -207,8 +218,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
private float mLongSwipeDisplacement = 0;
|
||||
private LongSwipeHelper mLongSwipeController;
|
||||
|
||||
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs,
|
||||
ActivityControlHelper<T> controller) {
|
||||
WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context,
|
||||
long touchTimeMs, ActivityControlHelper<T> controller) {
|
||||
this.id = id;
|
||||
mContext = context;
|
||||
mRunningTaskInfo = runningTaskInfo;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
|
@ -453,6 +465,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
"Can't change interaction type to " + interactionType);
|
||||
}
|
||||
mInteractionType = interactionType;
|
||||
mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub);
|
||||
|
||||
setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
|
||||
|
||||
|
@ -460,6 +473,34 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR);
|
||||
}
|
||||
|
||||
private void shiftAnimationDestinationForQuickscrub() {
|
||||
TransformedRect tempRect = new TransformedRect();
|
||||
mActivityControlHelper
|
||||
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
|
||||
mClipAnimationHelper.updateTargetRect(tempRect);
|
||||
|
||||
float offsetY =
|
||||
mActivityControlHelper.getTranslationYForQuickScrub(tempRect, mDp, mContext);
|
||||
float scale, offsetX;
|
||||
Resources res = mContext.getResources();
|
||||
|
||||
if (ActivityManagerWrapper.getInstance().getRecentTasks(2, UserHandle.myUserId()).size()
|
||||
< 2) {
|
||||
// There are not enough tasks, we don't need to shift
|
||||
offsetX = 0;
|
||||
scale = 1;
|
||||
} else {
|
||||
offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing)
|
||||
+ tempRect.rect.width();
|
||||
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
|
||||
res.getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
|
||||
scale = TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
}
|
||||
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
|
||||
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public void updateDisplacement(float displacement) {
|
||||
// We are moving in the negative x/y direction
|
||||
|
@ -658,7 +699,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
: STATE_SCALED_CONTROLLER_APP);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
mRecentsAnimationWrapper.runOnInit(anim::start);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
@ -786,30 +827,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
|||
|
||||
// Inform the last progress in case we skipped before.
|
||||
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
|
||||
|
||||
// Make sure the window follows the first task if it moves, e.g. during quick scrub.
|
||||
TaskView firstTask = mRecentsView.getPageAt(0);
|
||||
// The first task may be null if we are swiping up from a task that does not
|
||||
// appear in the list (i.e. the assistant)
|
||||
if (firstTask != null) {
|
||||
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
|
||||
int scrollForSecondTask = mRecentsView.getChildCount() > 1
|
||||
? mRecentsView.getScrollForPage(1) : scrollForFirstTask;
|
||||
float offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask;
|
||||
|
||||
TransformedRect tempRect = new TransformedRect();
|
||||
mActivityControlHelper
|
||||
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
|
||||
float distanceToReachEdge = mDp.widthPx / 2 + tempRect.rect.width() / 2 +
|
||||
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
float interpolation = Math.min(1,
|
||||
Math.abs(offsetFromFirstTask) / distanceToReachEdge);
|
||||
|
||||
mClipAnimationHelper.offsetTarget(
|
||||
firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask,
|
||||
mActivityControlHelper.getTranslationYForQuickScrub(mActivity),
|
||||
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFinishedTransitionToQuickScrub() {
|
||||
|
|
|
@ -507,6 +507,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
DeviceProfile dp = mActivity.getDeviceProfile();
|
||||
getTaskSize(dp, mTempRect);
|
||||
|
||||
// Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
|
||||
mTempRect.top -= mTaskTopMargin;
|
||||
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
|
||||
dp.availableWidthPx + mInsets.left - mTempRect.right,
|
||||
|
|
|
@ -250,12 +250,12 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
|||
setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
|
||||
}
|
||||
|
||||
public float getCurveScaleForInterpolation(float linearInterpolation) {
|
||||
public static float getCurveScaleForInterpolation(float linearInterpolation) {
|
||||
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
|
||||
return getCurveScaleForCurveInterpolation(curveInterpolation);
|
||||
}
|
||||
|
||||
private float getCurveScaleForCurveInterpolation(float curveInterpolation) {
|
||||
private static float getCurveScaleForCurveInterpolation(float curveInterpolation) {
|
||||
return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
|
||||
}
|
||||
|
||||
|
|
|
@ -1450,6 +1450,10 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
|||
|
||||
protected boolean snapToPage(int whichPage, int delta, int duration, boolean immediate,
|
||||
TimeInterpolator interpolator) {
|
||||
if (mFirstLayout) {
|
||||
setCurrentPage(whichPage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD) {
|
||||
duration *= Settings.System.getFloat(getContext().getContentResolver(),
|
||||
|
|
Loading…
Reference in New Issue