From e6fe1b59470b653f0275596cb8a211367dd61654 Mon Sep 17 00:00:00 2001 From: Peter Schiller Date: Fri, 29 Jul 2016 17:05:30 -0700 Subject: Simpler caret Bug: 30527159 Change-Id: I674de149e613c7adb567a13a288baa9877d36112 --- .../launcher3/allapps/AllAppsCaretController.java | 122 +++++++++++++++++++++ .../allapps/AllAppsTransitionController.java | 70 ++---------- 2 files changed, 129 insertions(+), 63 deletions(-) create mode 100644 src/com/android/launcher3/allapps/AllAppsCaretController.java (limited to 'src/com/android/launcher3') diff --git a/src/com/android/launcher3/allapps/AllAppsCaretController.java b/src/com/android/launcher3/allapps/AllAppsCaretController.java new file mode 100644 index 000000000..622322bfc --- /dev/null +++ b/src/com/android/launcher3/allapps/AllAppsCaretController.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 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.launcher3.allapps; + +import android.animation.ObjectAnimator; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.pageindicators.CaretDrawable; + +public class AllAppsCaretController { + // Determines when the caret should flip. Should be accessed via getThreshold() + private static final float CARET_THRESHOLD = 0.015f; + private static final float CARET_THRESHOLD_LAND = 0.5f; + // The velocity at which the caret will peak (i.e. exhibit a 90 degree bend) + private static final float PEAK_VELOCITY = VerticalPullDetector.RELEASE_VELOCITY_PX_MS * .7f; + + private Launcher mLauncher; + + private ObjectAnimator mCaretAnimator; + private CaretDrawable mCaretDrawable; + private float mLastCaretProgress; + private boolean mThresholdCrossed; + + public AllAppsCaretController(CaretDrawable caret, Launcher launcher) { + mLauncher = launcher; + mCaretDrawable = caret; + + final long caretAnimationDuration = launcher.getResources().getInteger( + R.integer.config_caretAnimationDuration); + final Interpolator caretInterpolator = AnimationUtils.loadInterpolator(launcher, + android.R.interpolator.fast_out_slow_in); + + // We will set values later + mCaretAnimator = ObjectAnimator.ofFloat(mCaretDrawable, "caretProgress", 0); + mCaretAnimator.setDuration(caretAnimationDuration); + mCaretAnimator.setInterpolator(caretInterpolator); + } + + /** + * Updates the state of the caret based on the progress of the {@link AllAppsContainerView}, as + * defined by the {@link AllAppsTransitionController}. Uses the container's velocity to adjust + * angle of caret. + * + * @param containerProgress The progress of the container in the range [0..1] + * @param velocity The velocity of the container + * @param dragging {@code true} if the container is being dragged + */ + public void updateCaret(float containerProgress, float velocity, boolean dragging) { + // If we're in portrait and the shift is not 0 or 1, adjust the caret based on velocity + if (getThreshold() < containerProgress && containerProgress < 1 - getThreshold() && + !mLauncher.useVerticalBarLayout()) { + mThresholdCrossed = true; + + // How fast are we moving as a percentage of the peak velocity? + final float pctOfFlingVelocity = Math.max(-1, Math.min(velocity / PEAK_VELOCITY, 1)); + + mCaretDrawable.setCaretProgress(pctOfFlingVelocity); + + // Set the last caret progress to this progress to prevent animator cancellation + mLastCaretProgress = pctOfFlingVelocity; + // Animate to neutral. This is necessary so the caret doesn't "freeze" when the + // container stops moving (e.g., during a drag or when the threshold is reached). + animateCaretToProgress(CaretDrawable.PROGRESS_CARET_NEUTRAL); + } else if (!dragging) { + // Otherwise, if we're not dragging, match the caret to the appropriate state + if (containerProgress <= getThreshold()) { // All Apps is up + animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_DOWN); + } else if (containerProgress >= 1 - getThreshold()) { // All Apps is down + animateCaretToProgress(CaretDrawable.PROGRESS_CARET_POINTING_UP); + } + } + } + + private void animateCaretToProgress(float progress) { + // If the new progress is the same as the last progress we animated to, terminate early + if (Float.compare(mLastCaretProgress, progress) == 0) { + return; + } + + if (mCaretAnimator.isRunning()) { + mCaretAnimator.cancel(); // Stop the animator in its tracks + } + + // Update the progress and start the animation + mLastCaretProgress = progress; + mCaretAnimator.setFloatValues(progress); + mCaretAnimator.start(); + } + + private float getThreshold() { + // In landscape, just return the landscape threshold. + if (mLauncher.useVerticalBarLayout()) { + return CARET_THRESHOLD_LAND; + } + + // Before the threshold is crossed, it is reported as zero. This makes the caret immediately + // responsive when a drag begins. After the threshold is crossed, we return the constant + // value. This means the caret will start its state-based adjustment sooner. That is, we + // won't have to wait until the panel is completely settled to begin animation. + return mThresholdCrossed ? CARET_THRESHOLD : 0f; + } + + public void onDragStart() { + mThresholdCrossed = false; + } +} diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index eb6c92628..a8c0422c9 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -11,7 +11,6 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.AccelerateInterpolator; -import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile; @@ -22,7 +21,6 @@ import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; -import com.android.launcher3.pageindicators.CaretDrawable; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.TouchController; @@ -56,11 +54,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul private Hotseat mHotseat; private int mHotseatBackgroundColor; - private ObjectAnimator mCaretAnimator; - private final long mCaretAnimationDuration; - private final Interpolator mCaretInterpolator; - private CaretDrawable mCaretDrawable; - private float mLastCaretProgress; + private AllAppsCaretController mCaretController; private float mStatusBarHeight; @@ -105,11 +99,6 @@ public class AllAppsTransitionController implements TouchController, VerticalPul mBezelSwipeUpHeight = l.getResources().getDimensionPixelSize( R.dimen.all_apps_bezel_swipe_height); - mCaretAnimationDuration = l.getResources().getInteger( - R.integer.config_caretAnimationDuration); - mCaretInterpolator = AnimationUtils.loadInterpolator(l, - R.interpolator.caret_animation_interpolator); - mEvaluator = new ArgbEvaluator(); mAllAppsBackgroundColor = l.getColor(R.color.all_apps_container_color); } @@ -196,6 +185,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul @Override public void onDragStart(boolean start) { + mCaretController.onDragStart(); cancelAnimation(); mCurrentAnimation = LauncherAnimUtils.createAnimatorSet(); mShiftStart = mAppsView.getTranslationY(); @@ -336,19 +326,15 @@ public class AllAppsTransitionController implements TouchController, VerticalPul return; } mWorkspace.setWorkspaceYTranslationAndAlpha( - PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), - interpolation); - updateCaret(progress); - updateLightStatusBar(shiftCurrent); + PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), interpolation); if (!mDetector.isDraggingState()) { mContainerVelocity = mDetector.computeVelocity(shiftCurrent - shiftPrevious, System.currentTimeMillis()); } - } - public float getContainerVelocity() { - return mContainerVelocity; + mCaretController.updateCaret(progress, mContainerVelocity, mDetector.isDraggingState()); + updateLightStatusBar(shiftCurrent); } public float getProgress() { @@ -513,56 +499,14 @@ public class AllAppsTransitionController implements TouchController, VerticalPul mCurrentAnimation = null; } - private void updateCaret(float shift) { - // Animate to a neutral state by default - float newCaretProgress = CaretDrawable.PROGRESS_CARET_NEUTRAL; - - // If we're in portrait and the shift is not 0 or 1, adjust the caret based on velocity - if (0f < shift && shift < 1f && !mLauncher.useVerticalBarLayout()) { - // How fast are we moving as a percentage of the minimum fling velocity? - final float pctOfFlingVelocity = Math.max(-1, Math.min( - mContainerVelocity / VerticalPullDetector.RELEASE_VELOCITY_PX_MS, 1)); - - mCaretDrawable.setCaretProgress(pctOfFlingVelocity); - - // Set the last caret progress to this progress to prevent animator cancellation - mLastCaretProgress = pctOfFlingVelocity; - } else if (!mDetector.isDraggingState()) { - // Otherwise, if we're not dragging, match the caret to the appropriate state - if (Float.compare(shift, 0f) == 0) { // All Apps is up - newCaretProgress = CaretDrawable.PROGRESS_CARET_POINTING_DOWN; - } else if (Float.compare(shift, 1f) == 0) { // All Apps is down - newCaretProgress = CaretDrawable.PROGRESS_CARET_POINTING_UP; - } - } - - // If the new progress is the same as the last progress we animated to, terminate early - if (Float.compare(mLastCaretProgress, newCaretProgress) == 0) { - return; - } - - if (mCaretAnimator.isRunning()) { - mCaretAnimator.cancel(); // Stop the animator in its tracks - } - - // Update the progress and start the animation - mLastCaretProgress = newCaretProgress; - mCaretAnimator.setFloatValues(newCaretProgress); - mCaretAnimator.start(); - } - public void setupViews(AllAppsContainerView appsView, Hotseat hotseat, Workspace workspace) { mAppsView = appsView; mHotseat = hotseat; mWorkspace = workspace; - mCaretDrawable = mWorkspace.getPageIndicator().getCaretDrawable(); mHotseat.addOnLayoutChangeListener(this); mHotseat.bringToFront(); - - // we will set values later - mCaretAnimator = ObjectAnimator.ofFloat(mCaretDrawable, "caretProgress", 0); - mCaretAnimator.setDuration(mCaretAnimationDuration); - mCaretAnimator.setInterpolator(mCaretInterpolator); + mCaretController = new AllAppsCaretController( + mWorkspace.getPageIndicator().getCaretDrawable(), mLauncher); } @Override -- cgit v1.2.3