1e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller/*
2e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * Copyright (C) 2016 The Android Open Source Project
3e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller *
4e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * Licensed under the Apache License, Version 2.0 (the "License");
5e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * you may not use this file except in compliance with the License.
6e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * You may obtain a copy of the License at
7e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller *
8e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller *      http://www.apache.org/licenses/LICENSE-2.0
9e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller *
10e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * Unless required by applicable law or agreed to in writing, software
11e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * distributed under the License is distributed on an "AS IS" BASIS,
12e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * See the License for the specific language governing permissions and
14e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller * limitations under the License.
15e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller */
16e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerpackage com.android.launcher3.allapps;
17e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
18e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport android.animation.ObjectAnimator;
19e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport android.view.animation.AnimationUtils;
20e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport android.view.animation.Interpolator;
21e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
22e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport com.android.launcher3.Launcher;
23e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport com.android.launcher3.R;
24e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerimport com.android.launcher3.pageindicators.CaretDrawable;
25f40e94955cba0ca351f587358b9e07496d132a1bHyunyoung Songimport com.android.launcher3.touch.SwipeDetector;
26e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
27e6fe1b59470b653f0275596cb8a211367dd61654Peter Schillerpublic class AllAppsCaretController {
28e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    // Determines when the caret should flip. Should be accessed via getThreshold()
29e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private static final float CARET_THRESHOLD = 0.015f;
30e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private static final float CARET_THRESHOLD_LAND = 0.5f;
31e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    // The velocity at which the caret will peak (i.e. exhibit a 90 degree bend)
32f40e94955cba0ca351f587358b9e07496d132a1bHyunyoung Song    private static final float PEAK_VELOCITY = SwipeDetector.RELEASE_VELOCITY_PX_MS * .7f;
33e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
34e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private Launcher mLauncher;
35e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
36e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private ObjectAnimator mCaretAnimator;
37e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private CaretDrawable mCaretDrawable;
38e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private float mLastCaretProgress;
39e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private boolean mThresholdCrossed;
40e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
41e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    public AllAppsCaretController(CaretDrawable caret, Launcher launcher) {
42e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mLauncher = launcher;
43e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretDrawable = caret;
44e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
45e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        final long caretAnimationDuration = launcher.getResources().getInteger(
46e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller                R.integer.config_caretAnimationDuration);
47e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        final Interpolator caretInterpolator = AnimationUtils.loadInterpolator(launcher,
48e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller                android.R.interpolator.fast_out_slow_in);
49e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
50e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // We will set values later
51e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretAnimator = ObjectAnimator.ofFloat(mCaretDrawable, "caretProgress", 0);
52e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretAnimator.setDuration(caretAnimationDuration);
53e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretAnimator.setInterpolator(caretInterpolator);
54e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    }
55e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
56e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    /**
57e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * Updates the state of the caret based on the progress of the {@link AllAppsContainerView}, as
58e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * defined by the {@link AllAppsTransitionController}. Uses the container's velocity to adjust
59e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * angle of caret.
60e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     *
61e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * @param containerProgress The progress of the container in the range [0..1]
62e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * @param velocity The velocity of the container
63e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     * @param dragging {@code true} if the container is being dragged
64e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller     */
65e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    public void updateCaret(float containerProgress, float velocity, boolean dragging) {
66e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // If we're in portrait and the shift is not 0 or 1, adjust the caret based on velocity
67e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        if (getThreshold() < containerProgress && containerProgress < 1 - getThreshold() &&
68e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller                !mLauncher.useVerticalBarLayout()) {
69e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            mThresholdCrossed = true;
70e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
71e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            // How fast are we moving as a percentage of the peak velocity?
72e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            final float pctOfFlingVelocity = Math.max(-1, Math.min(velocity / PEAK_VELOCITY, 1));
73e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
74e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            mCaretDrawable.setCaretProgress(pctOfFlingVelocity);
75e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
76e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            // Set the last caret progress to this progress to prevent animator cancellation
77e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            mLastCaretProgress = pctOfFlingVelocity;
78e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            // Animate to neutral. This is necessary so the caret doesn't "freeze" when the
79e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            // container stops moving (e.g., during a drag or when the threshold is reached).
80e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            animateCaretToProgress(CaretDrawable.PROGRESS_CARET_NEUTRAL);
81e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        } else if (!dragging) {
82e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            // Otherwise, if we're not dragging, match the caret to the appropriate state
83e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            if (containerProgress <= getThreshold()) { // All Apps is up
84e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller                animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_DOWN);
85e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            } else if (containerProgress >= 1 - getThreshold()) { // All Apps is down
86e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller                animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_UP);
87e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            }
88e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        }
89e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    }
90e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
91e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private void animateCaretToProgress(float progress) {
92e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // If the new progress is the same as the last progress we animated to, terminate early
93e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        if (Float.compare(mLastCaretProgress, progress) == 0) {
94e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            return;
95e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        }
96e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
97e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        if (mCaretAnimator.isRunning()) {
98e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            mCaretAnimator.cancel(); // Stop the animator in its tracks
99e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        }
100e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
101e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // Update the progress and start the animation
102e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mLastCaretProgress = progress;
103e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretAnimator.setFloatValues(progress);
104e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mCaretAnimator.start();
105e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    }
106e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
107e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    private float getThreshold() {
108e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // In landscape, just return the landscape threshold.
109e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        if (mLauncher.useVerticalBarLayout()) {
110e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller            return CARET_THRESHOLD_LAND;
111e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        }
112e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
113e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // Before the threshold is crossed, it is reported as zero. This makes the caret immediately
114e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // responsive when a drag begins. After the threshold is crossed, we return the constant
115e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // value. This means the caret will start its state-based adjustment sooner. That is, we
116e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        // won't have to wait until the panel is completely settled to begin animation.
117e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        return mThresholdCrossed ? CARET_THRESHOLD : 0f;
118e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    }
119e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller
120e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    public void onDragStart() {
121e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller        mThresholdCrossed = false;
122e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller    }
123e6fe1b59470b653f0275596cb8a211367dd61654Peter Schiller}
124