Merge changes I13dfced7,I1ff160cf into ub-launcher3-master

* changes:
  Scale adjacent task icon during swipe up
  Scroll recents side to side during swipe up from an app
This commit is contained in:
Tony Wickham
2019-01-08 21:08:08 +00:00
committed by Android (Google) Code Review
8 changed files with 197 additions and 58 deletions
@@ -49,7 +49,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
private static final String TAG = "OverviewSwipeController";
// Progress after which the transition is assumed to be a success in case user does not fling
private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
protected final T mActivity;
private final SwipeDetector mDetector;
@@ -44,6 +44,8 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -77,9 +79,6 @@ import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
/**
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
*/
@@ -21,11 +21,9 @@ import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.annotation.TargetApi;
@@ -192,7 +190,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
if (mPassedInitialSlop && mInteractionHandler != null) {
// Move
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
dispatchMotion(ev, displacement - mStartDisplacement);
}
break;
}
@@ -207,6 +205,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
}
}
private void dispatchMotion(MotionEvent ev, float displacement) {
mInteractionHandler.updateDisplacement(displacement);
boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
if (!isLandscape) {
mInteractionHandler.dispatchMotionEventToRecentsView(ev);
}
}
private void notifyGestureStarted() {
if (mInteractionHandler == null) {
return;
@@ -297,15 +303,16 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
*/
private void finishTouchTracking(MotionEvent ev) {
if (mPassedInitialSlop && mInteractionHandler != null) {
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
dispatchMotion(ev, getDisplacement(ev) - mStartDisplacement);
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
float velocity = isNavBarOnRight() ? mVelocityTracker.getXVelocity(mActivePointerId)
: isNavBarOnLeft() ? -mVelocityTracker.getXVelocity(mActivePointerId)
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocity = isNavBarOnRight() ? velocityX
: isNavBarOnLeft() ? -velocityX
: mVelocityTracker.getYVelocity(mActivePointerId);
mInteractionHandler.onGestureEnded(velocity);
mInteractionHandler.onGestureEnded(velocity, velocityX);
} else {
// Since we start touch tracking on DOWN, we may reach this state without actually
// starting the gesture. In that case, just cleanup immediately.
@@ -97,8 +97,8 @@ public class RecentsAnimationWrapper {
}
/**
* @param onFinishComplete A callback that runs after the animation controller has finished
* on the background thread.
* @param onFinishComplete A callback that runs on the main thread after the animation
* controller has finished on the background thread.
*/
public void finish(boolean toHome, Runnable onFinishComplete) {
if (!toHome) {
@@ -128,7 +128,7 @@ public class RecentsAnimationWrapper {
controller.finish(toHome);
if (onFinishComplete != null) {
onFinishComplete.run();
mMainThreadExecutor.execute(onFinishComplete);
}
}
}
@@ -46,10 +46,12 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import androidx.annotation.AnyThread;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
@@ -109,7 +111,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
// Interaction finish states
private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 5;
private static final int STATE_SCALED_CONTROLLER_APP = 1 << 6;
private static final int STATE_SCALED_CONTROLLER_LAST_TASK = 1 << 6;
private static final int STATE_HANDLER_INVALIDATED = 1 << 7;
private static final int STATE_GESTURE_STARTED_QUICKSTEP = 1 << 8;
@@ -127,7 +129,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
private static final int STATE_SCREENSHOT_VIEW_SHOWN = 1 << 17;
private static final int STATE_RESUME_LAST_TASK = 1 << 18;
private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 19;
private static final int STATE_START_NEW_TASK = 1 << 19;
private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 20;
private static final int LAUNCHER_UI_STATES =
@@ -153,7 +156,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
"STATE_ACTIVITY_MULTIPLIER_COMPLETE",
"STATE_APP_CONTROLLER_RECEIVED",
"STATE_SCALED_CONTROLLER_RECENTS",
"STATE_SCALED_CONTROLLER_APP",
"STATE_SCALED_CONTROLLER_LAST_TASK",
"STATE_HANDLER_INVALIDATED",
"STATE_GESTURE_STARTED_QUICKSTEP",
"STATE_GESTURE_STARTED_QUICKSCRUB",
@@ -166,6 +169,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
"STATE_SCREENSHOT_CAPTURED",
"STATE_SCREENSHOT_VIEW_SHOWN",
"STATE_RESUME_LAST_TASK",
"STATE_START_NEW_TASK",
"STATE_ASSIST_DATA_RECEIVED",
};
@@ -173,7 +177,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
public static final long MIN_SWIPE_DURATION = 80;
public static final long MIN_OVERSHOOT_DURATION = 120;
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
private static final float SWIPE_DURATION_MULTIPLIER =
Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW));
@@ -190,6 +194,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
// visible.
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
private boolean mDispatchedDownEvent;
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
private float mShiftAtGestureStart = 0;
@@ -298,10 +303,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
this::sendRemoteAnimationsToAnimationFactory);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP,
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_LAST_TASK,
this::resumeLastTaskForQuickstep);
mStateCallback.addCallback(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
this::resumeLastTask);
mStateCallback.addCallback(STATE_START_NEW_TASK | STATE_APP_CONTROLLER_RECEIVED,
this::startNewTask);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE
@@ -327,7 +334,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
this::invalidateHandlerWithLauncher);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED
| STATE_SCALED_CONTROLLER_APP,
| STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
mStateCallback.addCallback(QUICK_SCRUB_START_UI_STATE, this::onQuickScrubStartUi);
@@ -410,6 +417,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, (applier) -> {
mSyncTransactionApplier = applier;
});
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
updateFinalShift();
});
mQuickScrubController = mRecentsView.getQuickScrubController();
mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
@@ -535,15 +545,39 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
} 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);
scale = getTaskCurveScaleForOffsetX(offsetX, tempRect.rect.width());
}
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 +
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
return TaskView.getCurveScaleForInterpolation(interpolation);
}
@WorkerThread
public void dispatchMotionEventToRecentsView(MotionEvent event) {
if (mRecentsView == null) {
return;
}
// Pass the motion events to RecentsView to allow scrolling during swipe up.
if (mDispatchedDownEvent) {
mRecentsView.dispatchTouchEvent(event);
} else {
// The first event we dispatch should be ACTION_DOWN.
mDispatchedDownEvent = true;
MotionEvent downEvent = MotionEvent.obtain(event);
downEvent.setAction(MotionEvent.ACTION_DOWN);
int flags = downEvent.getEdgeFlags();
downEvent.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
mRecentsView.dispatchTouchEvent(downEvent);
downEvent.recycle();
}
}
@WorkerThread
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
@@ -588,11 +622,21 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
float offsetX = 0;
if (mRecentsView != null && mInteractionType == INTERACTION_NORMAL) {
int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(
mRecentsView.getRunningTaskView()));
offsetX = startScroll - mRecentsView.getScrollX();
offsetX *= mRecentsView.getScaleX();
}
float offsetScale = getTaskCurveScaleForOffsetX(offsetX,
mClipAnimationHelper.getTargetRect().width());
SyncRtSurfaceTransactionApplierCompat syncTransactionApplier
= Looper.myLooper() == mMainThreadHandler.getLooper()
? mSyncTransactionApplier
: null;
mTransformParams.setProgress(shift).setSyncTransactionApplier(syncTransactionApplier);
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale)
.setSyncTransactionApplier(syncTransactionApplier);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
@@ -621,10 +665,17 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
// Update insets of the next previous task, as we might switch to it.
TaskView nextTaskView = mRecentsView == null ? null : mRecentsView.getNextTaskView();
if (mInteractionType == INTERACTION_NORMAL && nextTaskView != null) {
nextTaskView.setFullscreenProgress(1 - mCurrentShift.value);
// Update insets of the adjacent tasks, as we might switch to them.
int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex();
if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) {
TaskView nextTaskView = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
TaskView prevTaskView = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
if (nextTaskView != null) {
nextTaskView.setFullscreenProgress(1 - mCurrentShift.value);
}
if (prevTaskView != null) {
prevTaskView.setFullscreenProgress(1 - mCurrentShift.value);
}
}
if (mLauncherTransitionController == null || mLauncherTransitionController
@@ -714,7 +765,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
}
@WorkerThread
public void onGestureEnded(float endVelocity) {
public void onGestureEnded(float endVelocity, float velocityX) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
@@ -723,9 +774,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
if (mBgLongSwipeMode) {
executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling));
executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling, velocityX));
} else {
handleNormalGestureEnd(endVelocity, isFling);
handleNormalGestureEnd(endVelocity, isFling, velocityX);
}
}
@@ -742,16 +793,21 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mTouchInteractionLog);
}
private void handleNormalGestureEnd(float endVelocity, boolean isFling) {
private void handleNormalGestureEnd(float endVelocity, boolean isFling, float velocityX) {
float velocityPxPerMs = endVelocity / 1000;
float velocityXPxPerMs = velocityX / 1000;
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
final boolean goingToHome;
float endShift;
final float startShift;
Interpolator interpolator = DEACCEL;
final int nextPage = mRecentsView != null ? mRecentsView.getNextPage() : -1;
final int runningTaskIndex = mRecentsView != null ? mRecentsView.getRunningTaskIndex() : -1;
boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex;
final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW;
if (!isFling) {
goingToHome = currentShift >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted;
goingToHome = reachedOverviewThreshold && mGestureStarted;
endShift = goingToHome ? 1 : 0;
long expectedDuration = Math.abs(Math.round((endShift - currentShift)
* MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
@@ -759,7 +815,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
startShift = currentShift;
interpolator = goingToHome ? OVERSHOOT_1_2 : DEACCEL;
} else {
goingToHome = endVelocity < 0;
// If user scrolled to a new task, only go to home (overview) if they already passed
// the overview threshold. Otherwise, we'll snap to the new task and launch it.
goingToHome = endVelocity < 0 && (!goingToNewTask || reachedOverviewThreshold);
endShift = goingToHome ? 1 : 0;
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs
* SINGLE_FRAME_MS / mTransitionDragLength, 0, 1);
@@ -786,9 +844,29 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
}
if (goingToHome) {
mRecentsAnimationWrapper.enableTouchProxy();
} else if (goingToNewTask) {
// We aren't goingToHome, and user scrolled/flung to a new task; snap to the closest
// task in that direction and launch it (in startNewTask()).
int taskToLaunch = runningTaskIndex + (nextPage > runningTaskIndex ? 1 : - 1);
if (taskToLaunch >= mRecentsView.getTaskViewCount()) {
// Scrolled to Clear all button, snap back to current task and resume it.
mRecentsView.snapToPage(runningTaskIndex, Math.toIntExact(duration));
goingToNewTask = false;
} else {
float distance = Math.abs(mRecentsView.getScrollForPage(taskToLaunch)
- mRecentsView.getScrollX());
int durationX = (int) Math.abs(distance / velocityXPxPerMs);
if (durationX > MAX_SWIPE_DURATION) {
durationX = Math.toIntExact(MAX_SWIPE_DURATION);
}
interpolator = Interpolators.scrollInterpolatorForVelocity(velocityXPxPerMs);
mRecentsView.snapToPage(taskToLaunch, durationX, interpolator);
duration = Math.max(duration, durationX);
}
}
animateToProgress(startShift, endShift, duration, interpolator, goingToHome);
animateToProgress(startShift, endShift, duration, interpolator, goingToHome,
goingToNewTask);
}
private void doLogGesture(boolean toLauncher) {
@@ -814,22 +892,26 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
private void animateToProgress(float start, float end, long duration,
Interpolator interpolator, boolean goingToHome) {
Interpolator interpolator, boolean goingToHome, boolean goingToNewTask) {
mRecentsAnimationWrapper.runOnInit(() -> animateToProgressInternal(start, end, duration,
interpolator, goingToHome));
interpolator, goingToHome, goingToNewTask));
}
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, boolean goingToHome) {
Interpolator interpolator, boolean goingToHome, boolean goingToNewTask) {
mIsGoingToHome = goingToHome;
ObjectAnimator anim = mCurrentShift.animateToValue(start, end).setDuration(duration);
anim.setInterpolator(interpolator);
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
int recentsState = STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
| STATE_SCREENSHOT_VIEW_SHOWN;
setStateOnUiThread(mIsGoingToHome
? (STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
| STATE_SCREENSHOT_VIEW_SHOWN) : STATE_SCALED_CONTROLLER_APP);
? recentsState
: goingToNewTask
? STATE_START_NEW_TASK
: STATE_SCALED_CONTROLLER_LAST_TASK);
}
});
anim.start();
@@ -872,6 +954,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mTouchInteractionLog.finishRecentsAnimation(false);
}
@UiThread
private void startNewTask() {
// Launch the task user scrolled to (mRecentsView.getNextPage()).
mRecentsAnimationWrapper.finish(true /* toHome */, () -> {
mRecentsView.getTaskViewAt(mRecentsView.getNextPage()).launchTask(false,
result -> setStateOnUiThread(STATE_HANDLER_INVALIDATED),
mMainThreadHandler);
});
mTouchInteractionLog.finishRecentsAnimation(false);
doLogGesture(false /* toLauncher */);
}
public void reset() {
if (mInteractionType != INTERACTION_QUICK_SCRUB) {
// Only invalidate the handler if we are not quick scrubbing, otherwise, it will be
@@ -889,6 +983,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
mActivityInitListener.unregister();
mTaskSnapshot = null;
if (mRecentsView != null) {
mRecentsView.setOnScrollChangeListener(null);
}
}
private void invalidateHandlerWithLauncher() {
@@ -999,7 +1097,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
long duration = FeatureFlags.QUICK_SWITCH.get()
? QUICK_SWITCH_FROM_APP_START_DURATION
: QUICK_SCRUB_FROM_APP_START_DURATION;
animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, true /* goingToHome */);
animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, true /* goingToHome */,
false /* goingToNewTask */);
}
private void onQuickScrubStartUi() {
@@ -1152,10 +1251,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
}
private void onLongSwipeGestureFinishUi(float velocity, boolean isFling) {
private void onLongSwipeGestureFinishUi(float velocity, boolean isFling, float velocityX) {
if (!mUiLongSwipeMode || mLongSwipeController == null) {
mUiLongSwipeMode = false;
handleNormalGestureEnd(velocity, isFling);
handleNormalGestureEnd(velocity, isFling, velocityX);
return;
}
mUiLongSwipeMode = false;
@@ -154,10 +154,11 @@ public class ClipAnimationHelper {
public RectF applyTransform(RemoteAnimationTargetSet targetSet, TransformParams params) {
RectF currentRect;
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale * params.offsetScale);
float offsetYProgress = mOffsetYInterpolator.getInterpolation(params.progress);
float progress = mInterpolator.getInterpolation(params.progress);
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
currentRect.offset(params.offsetX, 0);
synchronized (mTargetOffset) {
// Stay lined up with the center of the target, since it moves for quick scrub.
@@ -353,10 +354,14 @@ public class ClipAnimationHelper {
public static class TransformParams {
float progress;
float offsetX;
float offsetScale;
SyncRtSurfaceTransactionApplierCompat syncTransactionApplier;
public TransformParams() {
progress = 0;
offsetX = 0;
offsetScale = 1;
}
public TransformParams setProgress(float progress) {
@@ -364,6 +369,16 @@ public class ClipAnimationHelper {
return this;
}
public TransformParams setOffsetX(float offsetX) {
this.offsetX = offsetX;
return this;
}
public TransformParams setOffsetScale(float offsetScale) {
this.offsetScale = offsetScale;
return this;
}
public TransformParams setSyncTransactionApplier(
SyncRtSurfaceTransactionApplierCompat applier) {
this.syncTransactionApplier = applier;
@@ -21,9 +21,11 @@ import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.uioverrides.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -60,6 +62,7 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ListView;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseActivity;
@@ -421,7 +424,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
final boolean clearAllButtonDeadZoneConsumed =
mClearAllButton.getAlpha() == 1
&& mClearAllButtonDeadZoneRect.contains(x, y);
if (!clearAllButtonDeadZoneConsumed
final boolean cameFromNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
if (!clearAllButtonDeadZoneConsumed && !cameFromNavBar
&& !mTaskViewDeadZoneRect.contains(x + getScrollX(), y)) {
mTouchDownToStartHome = true;
}
@@ -732,6 +736,11 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return getTaskView(mRunningTaskId);
}
public int getRunningTaskIndex() {
TaskView tv = getRunningTaskView();
return tv == null ? -1 : indexOfChild(tv);
}
/**
* Hides the tile associated with {@link #mRunningTaskId}
*/
@@ -756,8 +765,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
setRunningTaskIconScaledDown(runningTaskIconScaledDown);
setRunningTaskHidden(runningTaskTileHidden);
TaskView tv = getRunningTaskView();
setCurrentPage(tv == null ? 0 : indexOfChild(tv));
setCurrentPage(getRunningTaskIndex());
// Load the tasks (if the loading is already
mTaskListChangeId = mModel.getTasks(this::applyLoadPlan);
@@ -1346,7 +1354,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
: 0);
// Passing the threshold from taskview to fullscreen app will vibrate
final boolean passed = animator.getAnimatedFraction() >= MIN_PROGRESS_FOR_OVERVIEW;
final boolean passed = animator.getAnimatedFraction() >= SUCCESS_TRANSITION_PROGRESS;
if (passed != passedOverviewThreshold[0]) {
passedOverviewThreshold[0] = passed;
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
@@ -46,7 +46,7 @@ import android.widget.Toast;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.RecentsModel;
@@ -119,7 +119,7 @@ public class TaskView extends FrameLayout implements PageCallbacks {
new FloatProperty<TaskView>("focusTransition") {
@Override
public void setValue(TaskView taskView, float v) {
taskView.setIconAndDimTransitionProgress(v);
taskView.setIconAndDimTransitionProgress(v, false /* invert */);
}
@Override
@@ -316,11 +316,17 @@ public class TaskView extends FrameLayout implements PageCallbacks {
}
}
private void setIconAndDimTransitionProgress(float progress) {
private void setIconAndDimTransitionProgress(float progress, boolean invert) {
if (invert) {
progress = 1 - progress;
}
mFocusTransitionProgress = progress;
mSnapshotView.setDimAlphaMultipler(progress);
float scale = FAST_OUT_SLOW_IN.getInterpolation(Utilities.boundToRange(
progress * DIM_ANIM_DURATION / SCALE_ICON_DURATION, 0, 1));
float iconScalePercentage = (float) SCALE_ICON_DURATION / DIM_ANIM_DURATION;
float lowerClamp = invert ? 1f - iconScalePercentage : 0;
float upperClamp = invert ? 1 : iconScalePercentage;
float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
.getInterpolation(progress);
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
}
@@ -341,10 +347,14 @@ public class TaskView extends FrameLayout implements PageCallbacks {
}
protected void setIconScaleAndDim(float iconScale) {
setIconScaleAndDim(iconScale, false);
}
private void setIconScaleAndDim(float iconScale, boolean invert) {
if (mIconAndDimAnimator != null) {
mIconAndDimAnimator.cancel();
}
setIconAndDimTransitionProgress(iconScale);
setIconAndDimTransitionProgress(iconScale, invert);
}
public void resetVisualProperties() {
@@ -524,7 +534,8 @@ public class TaskView extends FrameLayout implements PageCallbacks {
}
mFullscreenProgress = progress;
boolean isFullscreen = mFullscreenProgress > 0;
mIconView.setVisibility(isFullscreen ? INVISIBLE : VISIBLE);
setIconScaleAndDim(progress, true /* invert */);
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
setClipChildren(!isFullscreen);
setClipToPadding(!isFullscreen);
getThumbnail().invalidate();