Search in sources :

Example 1 with DISMISS_ALPHA

use of com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA in project android_packages_apps_Launcher3 by AOSPA.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Example 2 with DISMISS_ALPHA

use of com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA in project android_packages_apps_Launcher3 by ArrowOS.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Example 3 with DISMISS_ALPHA

use of com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA in project android_packages_apps_Launcher3 by ProtonAOSP.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Example 4 with DISMISS_ALPHA

use of com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA in project android_packages_apps_404Launcher by P-404.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Aggregations

Animator (android.animation.Animator)4 AnimatorListenerAdapter (android.animation.AnimatorListenerAdapter)4 AnimatorSet (android.animation.AnimatorSet)4 LayoutTransition (android.animation.LayoutTransition)4 TransitionListener (android.animation.LayoutTransition.TransitionListener)4 ObjectAnimator (android.animation.ObjectAnimator)4 PropertyValuesHolder (android.animation.PropertyValuesHolder)4 ValueAnimator (android.animation.ValueAnimator)4 TargetApi (android.annotation.TargetApi)4 RunningTaskInfo (android.app.ActivityManager.RunningTaskInfo)4 Context (android.content.Context)4 LocusId (android.content.LocusId)4 Configuration (android.content.res.Configuration)4 BlendMode (android.graphics.BlendMode)4 Canvas (android.graphics.Canvas)4 Color (android.graphics.Color)4 Matrix (android.graphics.Matrix)4 Point (android.graphics.Point)4 PointF (android.graphics.PointF)4 Rect (android.graphics.Rect)4