Loading quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java +17 −19 Original line number Diff line number Diff line Loading @@ -18,14 +18,11 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.util.Log; import android.view.MotionEvent; Loading @@ -43,6 +40,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TouchController; import com.android.quickstep.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; Loading @@ -65,6 +63,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter private final RecentsView mRecentsView; private final int[] mTempCords = new int[2]; private PendingAnimation mPendingAnimation; private AnimatorPlaybackController mCurrentAnimation; private boolean mCurrentAnimationIsGoingUp; Loading Loading @@ -178,6 +177,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter if (mCurrentAnimation != null) { mCurrentAnimation.setPlayFraction(0); } if (mPendingAnimation != null) { mPendingAnimation.finish(false); mPendingAnimation = null; } mCurrentAnimationIsGoingUp = goingUp; float range = mLauncher.getAllAppsController().getShiftRange(); long maxDuration = (long) (2 * range); Loading @@ -194,19 +198,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter } } else { if (goingUp) { AnimatorSet anim = new AnimatorSet(); ObjectAnimator translate = ObjectAnimator.ofFloat( mTaskBeingDragged, View.TRANSLATION_Y, -mTaskBeingDragged.getBottom()); translate.setInterpolator(LINEAR); translate.setDuration(maxDuration); anim.play(translate); ObjectAnimator alpha = ObjectAnimator.ofFloat(mTaskBeingDragged, View.ALPHA, 0); alpha.setInterpolator(DEACCEL_1_5); alpha.setDuration(maxDuration); anim.play(alpha); mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration); mEndDisplacement = -mTaskBeingDragged.getBottom(); mPendingAnimation = mRecentsView .createTaskDismissAnimation(mTaskBeingDragged, maxDuration); mCurrentAnimation = AnimatorPlaybackController .wrap(mPendingAnimation.anim, maxDuration); mEndDisplacement = -mTaskBeingDragged.getHeight(); } else { AnimatorSet anim = new AnimatorSet(); // TODO: Setup a zoom animation Loading Loading @@ -292,15 +288,17 @@ public class OverviewSwipeController extends AnimatorListenerAdapter } private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) { if (mPendingAnimation != null) { mPendingAnimation.finish(wasSuccess); mPendingAnimation = null; } if (mTaskBeingDragged == null) { LauncherState state = wasSuccess ? (mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW; mLauncher.getStateManager().goToState(state, false); } else if (wasSuccess) { if (mCurrentAnimationIsGoingUp) { mRecentsView.onTaskDismissed(mTaskBeingDragged); } else { if (!mCurrentAnimationIsGoingUp) { mTaskBeingDragged.launchTask(false); mLauncher.getUserEventDispatcher().logTaskLaunch(logAction, Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent()); Loading quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +1 −4 Original line number Diff line number Diff line Loading @@ -57,10 +57,7 @@ public class RecentsViewStateController implements StateHandler { setVisibility(state.overviewUi); setTransitionProgress(state.overviewUi ? 1 : 0); if (state.overviewUi) { for (int i = 0; i < mRecentsView.getPageCount(); i++) { ((TaskView) mRecentsView.getPageAt(i)).resetVisualProperties(); } mRecentsView.updateCurveProperties(); mRecentsView.resetTaskVisuals(); } } Loading quickstep/src/com/android/quickstep/PendingAnimation.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep; import android.animation.AnimatorSet; import android.annotation.TargetApi; import android.os.Build; import java.util.ArrayList; import java.util.function.Consumer; /** * Utility class to keep track of a running animation. * * This class allows attaching end callbacks to an animation is intended to be used with * {@link com.android.launcher3.anim.AnimatorPlaybackController}, since in that case * AnimationListeners are not properly dispatched. */ @TargetApi(Build.VERSION_CODES.O) public class PendingAnimation { private final ArrayList<Consumer<Boolean>> mEndListeners = new ArrayList<>(); public final AnimatorSet anim; public PendingAnimation(AnimatorSet anim) { this.anim = anim; } public void finish(boolean isSuccess) { for (Consumer<Boolean> listeners : mEndListeners) { listeners.accept(isSuccess); } mEndListeners.clear(); } public void addEndListener(Consumer<Boolean> listener) { mEndListeners.add(listener); } } quickstep/src/com/android/quickstep/views/RecentsView.java +105 −49 Original line number Diff line number Diff line Loading @@ -16,23 +16,32 @@ package com.android.quickstep.views; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.LINEAR; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.quickstep.PendingAnimation; import com.android.quickstep.QuickScrubController; import com.android.quickstep.RecentsModel; import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan; Loading @@ -49,6 +58,7 @@ import java.util.ArrayList; /** * A list of recent tasks. */ @TargetApi(Build.VERSION_CODES.P) public abstract class RecentsView<T extends BaseActivity> extends PagedView implements OnSharedPreferenceChangeListener { Loading Loading @@ -90,14 +100,14 @@ public abstract class RecentsView<T extends BaseActivity> private boolean mOverviewStateEnabled; private boolean mTaskStackListenerRegistered; private LayoutTransition mLayoutTransition; private Runnable mNextPageSwitchRunnable; private PendingAnimation mPendingAnimation; public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); enableFreeScroll(true); setupLayoutTransition(); setClipToOutline(true); mFastFlingVelocity = getResources() Loading Loading @@ -136,33 +146,6 @@ public abstract class RecentsView<T extends BaseActivity> return null; } private void setupLayoutTransition() { // We want to show layout transitions when pages are deleted, to close the gap. // TODO: We should this manually so we can control the animation (fill in the gap as the // dismissing task is being tracked, and also so we can update the visible task data during // the transition. For now, the workaround is to expand the visible tasks to load. mLayoutTransition = new LayoutTransition(); mLayoutTransition.enableTransitionType(LayoutTransition.DISAPPEARING); mLayoutTransition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); mLayoutTransition.disableTransitionType(LayoutTransition.APPEARING); mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); mLayoutTransition.addTransitionListener(new TransitionListener() { @Override public void startTransition(LayoutTransition layoutTransition, ViewGroup viewGroup, View view, int i) { loadVisibleTaskData(); } @Override public void endTransition(LayoutTransition layoutTransition, ViewGroup viewGroup, View view, int i) { loadVisibleTaskData(); } }); setLayoutTransition(mLayoutTransition); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); Loading Loading @@ -231,6 +214,10 @@ public abstract class RecentsView<T extends BaseActivity> } private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) { if (mPendingAnimation != null) { mPendingAnimation.addEndListener((b) -> applyLoadPlan(loadPlan)); return; } TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null; if (stack == null) { removeAllViews(); Loading @@ -243,7 +230,6 @@ public abstract class RecentsView<T extends BaseActivity> // necessary) final LayoutInflater inflater = LayoutInflater.from(getContext()); final ArrayList<Task> tasks = new ArrayList<>(stack.getTasks()); setLayoutTransition(null); final int requiredChildCount = tasks.size(); for (int i = getChildCount(); i < requiredChildCount; i++) { Loading @@ -254,7 +240,6 @@ public abstract class RecentsView<T extends BaseActivity> final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1); removeView(taskView); } setLayoutTransition(mLayoutTransition); // Unload existing visible task data unloadVisibleTaskData(); Loading @@ -265,12 +250,8 @@ public abstract class RecentsView<T extends BaseActivity> final Task task = tasks.get(i); final TaskView taskView = (TaskView) getChildAt(pageIndex); taskView.bind(task); taskView.resetVisualProperties(); } updateCurveProperties(); // Update the set of visible task's data loadVisibleTaskData(); resetTaskVisuals(); applyIconScale(false /* animate */); if (oldChildCount != getChildCount()) { Loading @@ -278,6 +259,16 @@ public abstract class RecentsView<T extends BaseActivity> } } public void resetTaskVisuals() { for (int i = getChildCount() - 1; i >= 0; i--) { ((TaskView) getChildAt(i)).resetVisualProperties(); } updateCurveProperties(); // Update the set of visible task's data loadVisibleTaskData(); } private void updateTaskStackListenerState() { boolean registerStackListener = mOverviewStateEnabled && isAttachedToWindow() && getWindowVisibility() == VISIBLE; Loading Loading @@ -375,7 +366,7 @@ public abstract class RecentsView<T extends BaseActivity> final int pageCount = getPageCount(); for (int i = 0; i < pageCount; i++) { View page = getPageAt(i); int pageCenter = page.getLeft() + halfPageWidth; float pageCenter = page.getLeft() + page.getTranslationX() + halfPageWidth; float distanceFromScreenCenter = screenCenter - pageCenter; float distanceToReachEdge = halfScreenWidth + halfPageWidth + pageSpacing; mScrollState.linearInterpolation = Math.min(1, Loading Loading @@ -432,13 +423,6 @@ public abstract class RecentsView<T extends BaseActivity> mHasVisibleTaskData.clear(); } public void onTaskDismissed(TaskView taskView) { ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id); removeView(taskView); if (getChildCount() == 0) { onAllTasksRemoved(); } } protected abstract void onAllTasksRemoved(); Loading Loading @@ -470,11 +454,9 @@ public abstract class RecentsView<T extends BaseActivity> if (getChildCount() == 0) { needsReload = true; // Add an empty view for now setLayoutTransition(null); final TaskView taskView = (TaskView) LayoutInflater.from(getContext()) .inflate(R.layout.task, this, false); addView(taskView, 0); setLayoutTransition(mLayoutTransition); } mRunningTaskId = runningTaskId; setCurrentPage(0); Loading Loading @@ -529,4 +511,78 @@ public abstract class RecentsView<T extends BaseActivity> */ public float linearInterpolation; } public PendingAnimation createTaskDismissAnimation(TaskView taskView, long duration) { if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) { throw new IllegalStateException("Another pending animation is still running"); } AnimatorSet anim = new AnimatorSet(); PendingAnimation pendingAnimation = new PendingAnimation(anim); int count = getChildCount(); if (count == 0) { return pendingAnimation; } int[] oldScroll = new int[count]; getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC); int[] newScroll = new int[count]; getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView); int maxScrollDiff = 0; int lastPage = mIsRtl ? 0 : count - 1; if (getChildAt(lastPage) == taskView) { if (count > 1) { int secondLastPage = mIsRtl ? 1 : count - 2; maxScrollDiff = oldScroll[lastPage] - newScroll[secondLastPage]; } } boolean needsCurveUpdates = false; for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child == taskView) { addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim); addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()), duration, LINEAR, anim); } else { int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff; if (scrollDiff != 0) { addAnim(ObjectAnimator.ofFloat(child, TRANSLATION_X, scrollDiff), duration, ACCEL, anim); needsCurveUpdates = true; } } } if (needsCurveUpdates) { ValueAnimator va = ValueAnimator.ofFloat(0, 1); va.addUpdateListener((a) -> updateCurveProperties()); anim.play(va); } // Add a tiny bit of translation Z, so that it draws on top of other views taskView.setTranslationZ(0.1f); mPendingAnimation = pendingAnimation; mPendingAnimation.addEndListener((isSuccess) -> { if (isSuccess) { ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id); removeView(taskView); if (getChildCount() == 0) { onAllTasksRemoved(); } } resetTaskVisuals(); mPendingAnimation = null; }); return pendingAnimation; } private static void addAnim(ObjectAnimator anim, long duration, TimeInterpolator interpolator, AnimatorSet set) { anim.setDuration(duration).setInterpolator(interpolator); set.play(anim); } } quickstep/src/com/android/quickstep/views/TaskView.java +1 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback setScaleY(1f); setTranslationX(0f); setTranslationY(0f); setTranslationZ(0); setAlpha(1f); } Loading Loading
quickstep/src/com/android/launcher3/uioverrides/OverviewSwipeController.java +17 −19 Original line number Diff line number Diff line Loading @@ -18,14 +18,11 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.util.Log; import android.view.MotionEvent; Loading @@ -43,6 +40,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TouchController; import com.android.quickstep.PendingAnimation; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; Loading @@ -65,6 +63,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter private final RecentsView mRecentsView; private final int[] mTempCords = new int[2]; private PendingAnimation mPendingAnimation; private AnimatorPlaybackController mCurrentAnimation; private boolean mCurrentAnimationIsGoingUp; Loading Loading @@ -178,6 +177,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter if (mCurrentAnimation != null) { mCurrentAnimation.setPlayFraction(0); } if (mPendingAnimation != null) { mPendingAnimation.finish(false); mPendingAnimation = null; } mCurrentAnimationIsGoingUp = goingUp; float range = mLauncher.getAllAppsController().getShiftRange(); long maxDuration = (long) (2 * range); Loading @@ -194,19 +198,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter } } else { if (goingUp) { AnimatorSet anim = new AnimatorSet(); ObjectAnimator translate = ObjectAnimator.ofFloat( mTaskBeingDragged, View.TRANSLATION_Y, -mTaskBeingDragged.getBottom()); translate.setInterpolator(LINEAR); translate.setDuration(maxDuration); anim.play(translate); ObjectAnimator alpha = ObjectAnimator.ofFloat(mTaskBeingDragged, View.ALPHA, 0); alpha.setInterpolator(DEACCEL_1_5); alpha.setDuration(maxDuration); anim.play(alpha); mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration); mEndDisplacement = -mTaskBeingDragged.getBottom(); mPendingAnimation = mRecentsView .createTaskDismissAnimation(mTaskBeingDragged, maxDuration); mCurrentAnimation = AnimatorPlaybackController .wrap(mPendingAnimation.anim, maxDuration); mEndDisplacement = -mTaskBeingDragged.getHeight(); } else { AnimatorSet anim = new AnimatorSet(); // TODO: Setup a zoom animation Loading Loading @@ -292,15 +288,17 @@ public class OverviewSwipeController extends AnimatorListenerAdapter } private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) { if (mPendingAnimation != null) { mPendingAnimation.finish(wasSuccess); mPendingAnimation = null; } if (mTaskBeingDragged == null) { LauncherState state = wasSuccess ? (mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW; mLauncher.getStateManager().goToState(state, false); } else if (wasSuccess) { if (mCurrentAnimationIsGoingUp) { mRecentsView.onTaskDismissed(mTaskBeingDragged); } else { if (!mCurrentAnimationIsGoingUp) { mTaskBeingDragged.launchTask(false); mLauncher.getUserEventDispatcher().logTaskLaunch(logAction, Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent()); Loading
quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +1 −4 Original line number Diff line number Diff line Loading @@ -57,10 +57,7 @@ public class RecentsViewStateController implements StateHandler { setVisibility(state.overviewUi); setTransitionProgress(state.overviewUi ? 1 : 0); if (state.overviewUi) { for (int i = 0; i < mRecentsView.getPageCount(); i++) { ((TaskView) mRecentsView.getPageAt(i)).resetVisualProperties(); } mRecentsView.updateCurveProperties(); mRecentsView.resetTaskVisuals(); } } Loading
quickstep/src/com/android/quickstep/PendingAnimation.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep; import android.animation.AnimatorSet; import android.annotation.TargetApi; import android.os.Build; import java.util.ArrayList; import java.util.function.Consumer; /** * Utility class to keep track of a running animation. * * This class allows attaching end callbacks to an animation is intended to be used with * {@link com.android.launcher3.anim.AnimatorPlaybackController}, since in that case * AnimationListeners are not properly dispatched. */ @TargetApi(Build.VERSION_CODES.O) public class PendingAnimation { private final ArrayList<Consumer<Boolean>> mEndListeners = new ArrayList<>(); public final AnimatorSet anim; public PendingAnimation(AnimatorSet anim) { this.anim = anim; } public void finish(boolean isSuccess) { for (Consumer<Boolean> listeners : mEndListeners) { listeners.accept(isSuccess); } mEndListeners.clear(); } public void addEndListener(Consumer<Boolean> listener) { mEndListeners.add(listener); } }
quickstep/src/com/android/quickstep/views/RecentsView.java +105 −49 Original line number Diff line number Diff line Loading @@ -16,23 +16,32 @@ package com.android.quickstep.views; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.LINEAR; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.quickstep.PendingAnimation; import com.android.quickstep.QuickScrubController; import com.android.quickstep.RecentsModel; import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan; Loading @@ -49,6 +58,7 @@ import java.util.ArrayList; /** * A list of recent tasks. */ @TargetApi(Build.VERSION_CODES.P) public abstract class RecentsView<T extends BaseActivity> extends PagedView implements OnSharedPreferenceChangeListener { Loading Loading @@ -90,14 +100,14 @@ public abstract class RecentsView<T extends BaseActivity> private boolean mOverviewStateEnabled; private boolean mTaskStackListenerRegistered; private LayoutTransition mLayoutTransition; private Runnable mNextPageSwitchRunnable; private PendingAnimation mPendingAnimation; public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); enableFreeScroll(true); setupLayoutTransition(); setClipToOutline(true); mFastFlingVelocity = getResources() Loading Loading @@ -136,33 +146,6 @@ public abstract class RecentsView<T extends BaseActivity> return null; } private void setupLayoutTransition() { // We want to show layout transitions when pages are deleted, to close the gap. // TODO: We should this manually so we can control the animation (fill in the gap as the // dismissing task is being tracked, and also so we can update the visible task data during // the transition. For now, the workaround is to expand the visible tasks to load. mLayoutTransition = new LayoutTransition(); mLayoutTransition.enableTransitionType(LayoutTransition.DISAPPEARING); mLayoutTransition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); mLayoutTransition.disableTransitionType(LayoutTransition.APPEARING); mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); mLayoutTransition.addTransitionListener(new TransitionListener() { @Override public void startTransition(LayoutTransition layoutTransition, ViewGroup viewGroup, View view, int i) { loadVisibleTaskData(); } @Override public void endTransition(LayoutTransition layoutTransition, ViewGroup viewGroup, View view, int i) { loadVisibleTaskData(); } }); setLayoutTransition(mLayoutTransition); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); Loading Loading @@ -231,6 +214,10 @@ public abstract class RecentsView<T extends BaseActivity> } private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) { if (mPendingAnimation != null) { mPendingAnimation.addEndListener((b) -> applyLoadPlan(loadPlan)); return; } TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null; if (stack == null) { removeAllViews(); Loading @@ -243,7 +230,6 @@ public abstract class RecentsView<T extends BaseActivity> // necessary) final LayoutInflater inflater = LayoutInflater.from(getContext()); final ArrayList<Task> tasks = new ArrayList<>(stack.getTasks()); setLayoutTransition(null); final int requiredChildCount = tasks.size(); for (int i = getChildCount(); i < requiredChildCount; i++) { Loading @@ -254,7 +240,6 @@ public abstract class RecentsView<T extends BaseActivity> final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1); removeView(taskView); } setLayoutTransition(mLayoutTransition); // Unload existing visible task data unloadVisibleTaskData(); Loading @@ -265,12 +250,8 @@ public abstract class RecentsView<T extends BaseActivity> final Task task = tasks.get(i); final TaskView taskView = (TaskView) getChildAt(pageIndex); taskView.bind(task); taskView.resetVisualProperties(); } updateCurveProperties(); // Update the set of visible task's data loadVisibleTaskData(); resetTaskVisuals(); applyIconScale(false /* animate */); if (oldChildCount != getChildCount()) { Loading @@ -278,6 +259,16 @@ public abstract class RecentsView<T extends BaseActivity> } } public void resetTaskVisuals() { for (int i = getChildCount() - 1; i >= 0; i--) { ((TaskView) getChildAt(i)).resetVisualProperties(); } updateCurveProperties(); // Update the set of visible task's data loadVisibleTaskData(); } private void updateTaskStackListenerState() { boolean registerStackListener = mOverviewStateEnabled && isAttachedToWindow() && getWindowVisibility() == VISIBLE; Loading Loading @@ -375,7 +366,7 @@ public abstract class RecentsView<T extends BaseActivity> final int pageCount = getPageCount(); for (int i = 0; i < pageCount; i++) { View page = getPageAt(i); int pageCenter = page.getLeft() + halfPageWidth; float pageCenter = page.getLeft() + page.getTranslationX() + halfPageWidth; float distanceFromScreenCenter = screenCenter - pageCenter; float distanceToReachEdge = halfScreenWidth + halfPageWidth + pageSpacing; mScrollState.linearInterpolation = Math.min(1, Loading Loading @@ -432,13 +423,6 @@ public abstract class RecentsView<T extends BaseActivity> mHasVisibleTaskData.clear(); } public void onTaskDismissed(TaskView taskView) { ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id); removeView(taskView); if (getChildCount() == 0) { onAllTasksRemoved(); } } protected abstract void onAllTasksRemoved(); Loading Loading @@ -470,11 +454,9 @@ public abstract class RecentsView<T extends BaseActivity> if (getChildCount() == 0) { needsReload = true; // Add an empty view for now setLayoutTransition(null); final TaskView taskView = (TaskView) LayoutInflater.from(getContext()) .inflate(R.layout.task, this, false); addView(taskView, 0); setLayoutTransition(mLayoutTransition); } mRunningTaskId = runningTaskId; setCurrentPage(0); Loading Loading @@ -529,4 +511,78 @@ public abstract class RecentsView<T extends BaseActivity> */ public float linearInterpolation; } public PendingAnimation createTaskDismissAnimation(TaskView taskView, long duration) { if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) { throw new IllegalStateException("Another pending animation is still running"); } AnimatorSet anim = new AnimatorSet(); PendingAnimation pendingAnimation = new PendingAnimation(anim); int count = getChildCount(); if (count == 0) { return pendingAnimation; } int[] oldScroll = new int[count]; getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC); int[] newScroll = new int[count]; getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView); int maxScrollDiff = 0; int lastPage = mIsRtl ? 0 : count - 1; if (getChildAt(lastPage) == taskView) { if (count > 1) { int secondLastPage = mIsRtl ? 1 : count - 2; maxScrollDiff = oldScroll[lastPage] - newScroll[secondLastPage]; } } boolean needsCurveUpdates = false; for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child == taskView) { addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim); addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()), duration, LINEAR, anim); } else { int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff; if (scrollDiff != 0) { addAnim(ObjectAnimator.ofFloat(child, TRANSLATION_X, scrollDiff), duration, ACCEL, anim); needsCurveUpdates = true; } } } if (needsCurveUpdates) { ValueAnimator va = ValueAnimator.ofFloat(0, 1); va.addUpdateListener((a) -> updateCurveProperties()); anim.play(va); } // Add a tiny bit of translation Z, so that it draws on top of other views taskView.setTranslationZ(0.1f); mPendingAnimation = pendingAnimation; mPendingAnimation.addEndListener((isSuccess) -> { if (isSuccess) { ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id); removeView(taskView); if (getChildCount() == 0) { onAllTasksRemoved(); } } resetTaskVisuals(); mPendingAnimation = null; }); return pendingAnimation; } private static void addAnim(ObjectAnimator anim, long duration, TimeInterpolator interpolator, AnimatorSet set) { anim.setDuration(duration).setInterpolator(interpolator); set.play(anim); } }
quickstep/src/com/android/quickstep/views/TaskView.java +1 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback setScaleY(1f); setTranslationX(0f); setTranslationY(0f); setTranslationZ(0); setAlpha(1f); } Loading