Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d6fe041 authored by Tony's avatar Tony
Browse files

Implement quick scrub and quick switch callbacks

Bug: 70180755
Change-Id: I011dd5b0435cea7ba493e83b973ce5be7d18c1f0
parent 1a52ef57
Loading
Loading
Loading
Loading
+1.26 KiB (92.3 KiB)

File changed.

No diff preview for this file type.

+3 −3
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.launcher3.uioverrides;

import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -31,9 +34,6 @@ import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsView;

import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;

public class RecentsViewStateController implements StateHandler {

    private final Launcher mLauncher;
+2 −1
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ public class WorkspaceCard extends FrameLayout implements PageCallbacks, OnClick

        mWorkspaceClickTarget.setOnClickListener(this);
        mWidgetsButton.setOnClickListener(this);
        setOnClickListener(this);
    }

    @Override
@@ -168,7 +169,7 @@ public class WorkspaceCard extends FrameLayout implements PageCallbacks, OnClick

    @Override
    public void onClick(View view) {
        if (view == mWorkspaceClickTarget) {
        if (view == mWorkspaceClickTarget || view == this) {
            mLauncher.getStateManager().goToState(NORMAL);
        } else if (view == mWidgetsButton) {
            WidgetsFullSheet.show(mLauncher, true);
+56 −5
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
    private static final long RECENTS_VIEW_VISIBILITY_DURATION = 150;
    private static final long MAX_SWIPE_DURATION = 200;
    private static final long MIN_SWIPE_DURATION = 80;
    private static final int QUICK_SWITCH_SNAP_DURATION = 120;

    // Ideal velocity for a smooth transition
    private static final float PIXEL_PER_MS = 2f;
@@ -98,6 +99,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
    private SnapshotDragView mDragView;
    private RecentsView mRecentsView;
    private RecentsViewStateController mStateController;
    private QuickScrubController mQuickScrubController;
    private Hotseat mHotseat;
    private AllAppsScrim mAllAppsScrim;
    private RecentsTaskLoadPlan mLoadPlan;
@@ -105,12 +107,16 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
    private boolean mLauncherReady;
    private boolean mTouchEndHandled;
    private float mCurrentDisplacement;
    private @TouchInteractionService.InteractionType int mInteractionType;
    private boolean mStartedQuickScrubFromHome;

    private Bitmap mTaskSnapshot;

    NavBarSwipeInteractionHandler(RunningTaskInfo runningTaskInfo, Context context) {
    NavBarSwipeInteractionHandler(RunningTaskInfo runningTaskInfo, Context context,
            @TouchInteractionService.InteractionType int interactionType) {
        mRunningTaskId = runningTaskInfo.id;
        mContext = context;
        mInteractionType = interactionType;
        WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);

        DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
@@ -191,11 +197,24 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
        mLauncher.getDragLayer().addView(mDragView);
        mDragView.setPivotX(0);
        mDragView.setPivotY(0);
        mRecentsView = mLauncher.getOverviewPanel();
        mRecentsView = launcher.getOverviewPanel();
        mStateController = mRecentsView.getStateController();
        mHotseat = mLauncher.getHotseat();
        mAllAppsScrim = mLauncher.findViewById(R.id.all_apps_scrim);

        boolean interactionIsQuick
                = mInteractionType == TouchInteractionService.INTERACTION_QUICK_SCRUB
                || mInteractionType == TouchInteractionService.INTERACTION_QUICK_SWITCH;
        mStartedQuickScrubFromHome = alreadyOnHome && interactionIsQuick;
        if (interactionIsQuick) {
            mQuickScrubController = mRecentsView.getQuickScrubController();
            mQuickScrubController.onQuickScrubStart(mStartedQuickScrubFromHome);
            animateToProgress(1f, MAX_SWIPE_DURATION);
            if (mStartedQuickScrubFromHome) {
                mDragView.setVisibility(View.INVISIBLE);
            }
        }

        // Optimization
        if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
            // All-apps search box is visible in vertical bar layout.
@@ -224,7 +243,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {

    @UiThread
    private void updateFinalShift() {
        if (!mLauncherReady) {
        if (!mLauncherReady || mStartedQuickScrubFromHome) {
            return;
        }

@@ -261,7 +280,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {

    private void setTaskPlanToUi() {
        mRecentsView.update(mLoadPlan);
        mRecentsView.initToPage(mRecentsView.getFirstTaskIndex());
        mRecentsView.initToPage(mStartedQuickScrubFromHome ? 0 : mRecentsView.getFirstTaskIndex());
        ObjectAnimator anim = mStateController.animateVisibility(true /* isVisible */)
                .setDuration(RECENTS_VIEW_VISIBILITY_DURATION);
        anim.addListener(new AnimationSuccessListener() {
@@ -301,7 +320,12 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
            }
        }

        ObjectAnimator anim = mCurrentShift.animateToValue(endShift).setDuration(duration);
        animateToProgress(endShift, duration);
    }

    /** Animates to the given progress, where 0 is the current app and 1 is overview. */
    private void animateToProgress(float progress, long duration) {
        ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration);
        anim.setInterpolator(Interpolators.SCROLL);
        anim.addListener(new AnimationSuccessListener() {
            @Override
@@ -345,5 +369,32 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
        if (currentRecentsPage instanceof TaskView) {
            ((TaskView) currentRecentsPage).animateIconToScale(1f);
        }
        if (mInteractionType == TouchInteractionService.INTERACTION_QUICK_SWITCH) {
            for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
                TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
                if (taskView.getTask().key.id != mRunningTaskId) {
                    mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION);
                    taskView.postDelayed(() -> {taskView.launchTask(true);},
                            QUICK_SWITCH_SNAP_DURATION);
                    break;
                }
            }
        } else if (mInteractionType == TouchInteractionService.INTERACTION_QUICK_SCRUB) {
            if (mQuickScrubController != null) {
                mQuickScrubController.snapToPageForCurrentQuickScrubSection();
            }
        }
    }

    public void onQuickScrubEnd() {
        if (mQuickScrubController != null) {
            mQuickScrubController.onQuickScrubEnd();
        }
    }

    public void onQuickScrubProgress(float progress) {
        if (mQuickScrubController != null) {
            mQuickScrubController.onQuickScrubProgress(progress);
        }
    }
}
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.quickstep;

import android.view.HapticFeedbackConstants;

import com.android.launcher3.Alarm;
import com.android.launcher3.Launcher;
import com.android.launcher3.OnAlarmListener;

/**
 * Responds to quick scrub callbacks to page through and launch recent tasks.
 *
 * The behavior is to evenly divide the progress into sections, each of which scrolls one page.
 * The first and last section set an alarm to auto-advance backwards or forwards, respectively.
 */
public class QuickScrubController implements OnAlarmListener {

    private static final int NUM_QUICK_SCRUB_SECTIONS = 5;
    private static final long AUTO_ADVANCE_DELAY = 500;
    private static final int QUICKSCRUB_END_SNAP_DURATION_PER_PAGE = 60;

    private Launcher mLauncher;
    private Alarm mAutoAdvanceAlarm;
    private RecentsView mRecentsView;

    private int mQuickScrubSection;
    private int mStartPage;

    public QuickScrubController(Launcher launcher) {
        mLauncher = launcher;
        mAutoAdvanceAlarm = new Alarm();
        mAutoAdvanceAlarm.setOnAlarmListener(this);
    }

    public void onQuickScrubStart(boolean startingFromHome) {
        mRecentsView = mLauncher.getOverviewPanel();
        mStartPage = startingFromHome ? 0 : mRecentsView.getFirstTaskIndex();
        mQuickScrubSection = 0;
    }

    public void onQuickScrubEnd() {
        mAutoAdvanceAlarm.cancelAlarm();
        if (mRecentsView != null) {
            int page = mRecentsView.getNextPage();
            // Settle on the page then launch it.
            int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
                    * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
            mRecentsView.snapToPage(page, snapDuration);
            mRecentsView.postDelayed(() -> {
                if (page < mRecentsView.getFirstTaskIndex()) {
                    mRecentsView.getPageAt(page).performClick();
                } else {
                    ((TaskView) mRecentsView.getPageAt(page)).launchTask(true);
                }
            }, snapDuration);
        }
    }

    public void onQuickScrubProgress(float progress) {
        int quickScrubSection = Math.round(progress * NUM_QUICK_SCRUB_SECTIONS);
        if (quickScrubSection != mQuickScrubSection) {
            int pageToGoTo = mRecentsView.getNextPage() + quickScrubSection - mQuickScrubSection;
            goToPageWithHaptic(pageToGoTo);
            if (quickScrubSection == NUM_QUICK_SCRUB_SECTIONS || quickScrubSection == 0) {
                mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
            } else {
                mAutoAdvanceAlarm.cancelAlarm();
            }
            mQuickScrubSection = quickScrubSection;
        }
    }

    public void snapToPageForCurrentQuickScrubSection() {
        goToPageWithHaptic(mRecentsView.getCurrentPage() + mQuickScrubSection);
    }

    private void goToPageWithHaptic(int pageToGoTo) {
        if (pageToGoTo != mRecentsView.getNextPage()) {
            mRecentsView.snapToPage(pageToGoTo);
            mRecentsView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP,
                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
        }
    }

    @Override
    public void onAlarm(Alarm alarm) {
        int currPage = mRecentsView.getNextPage();
        if (mQuickScrubSection == NUM_QUICK_SCRUB_SECTIONS
                && currPage < mRecentsView.getPageCount() - 1) {
            goToPageWithHaptic(currPage + 1);
        } else if (mQuickScrubSection == 0 && currPage > mStartPage) {
            goToPageWithHaptic(currPage - 1);
        }
        mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
    }
}
Loading