Merge "Fixing taskView not centered properly in available width" into ub-launcher3-edmonton
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index cd404d6..065663d 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -90,6 +90,7 @@
TASKSWITCHER = 12; // Recents UI Container (QuickStep)
APP = 13; // Foreground activity is another app (QuickStep)
TIP = 14; // Onboarding texts (QuickStep)
+ SIDELOADED_LAUNCHER = 15;
}
// Used to define what type of control a Target would represent.
@@ -148,11 +149,12 @@
enum Command {
HOME_INTENT = 0;
BACK = 1;
- ENTRY = 2; // Indicates entry to one of Launcher container type target
- // not using the HOME_INTENT
- CANCEL = 3; // Indicates that a confirmation screen was cancelled
- CONFIRM = 4; // Indicates thata confirmation screen was accepted
- STOP = 5; // Indicates onStop() was called (screen time out, power off)
+ ENTRY = 2; // Indicates entry to one of Launcher container type target
+ // not using the HOME_INTENT
+ CANCEL = 3; // Indicates that a confirmation screen was cancelled
+ CONFIRM = 4; // Indicates thata confirmation screen was accepted
+ STOP = 5; // Indicates onStop() was called (screen time out, power off)
+ RECENTS_BUTTON = 6; // Indicates that Recents button was pressed
}
optional Type type = 1;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
index b0f8d99..d86ba6a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java
@@ -68,8 +68,10 @@
@Override
public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
- // TODO: interpolate
- return LauncherState.OVERVIEW.getWorkspaceScaleAndTranslation(launcher);
+ float[] scaleAndTranslation = LauncherState.OVERVIEW.getWorkspaceScaleAndTranslation(
+ launcher);
+ scaleAndTranslation[0] = 1;
+ return scaleAndTranslation;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index ac940ea..3a49294 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -55,7 +55,7 @@
? workspacePage.getWidth() : launcher.getDeviceProfile().availableWidthPx;
recentsView.getTaskSize(sTempRect);
float scale = (float) sTempRect.width() / workspacePageWidth;
- float parallaxFactor = 0.4f;
+ float parallaxFactor = 0.5f;
return new float[]{scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor};
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 1d9ad91..54ecb28 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -197,7 +197,8 @@
}
};
animator.setFloatValues(0, 1);
- animator.setDuration(Math.max(expectedDuration, 300)).setInterpolator(LINEAR);
+ animator.setDuration(Math.min(expectedDuration, ATOMIC_DURATION))
+ .setInterpolator(LINEAR);
}
} else {
mFinishFastOnSecondTouch = false;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 79e3c42..e43b24a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,6 +15,10 @@
*/
package com.android.launcher3.uioverrides;
+import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
@@ -72,16 +76,17 @@
}
PropertySetter setter = config.getPropertySetter(builder);
float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
- setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], LINEAR);
- Interpolator transYInterpolator = LINEAR;
- if (toState == LauncherState.FAST_OVERVIEW) {
+ Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
+ setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], scaleInterpolator);
+ Interpolator transYInterpolator = scaleInterpolator;
+ if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
QUICK_SCRUB_TRANSLATION_Y_FACTOR);
}
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
transYInterpolator);
setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
- AGGRESSIVE_EASE_IN_OUT);
+ builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
if (!toState.overviewUi) {
builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index dc3f79c..a405735 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -21,16 +21,17 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import android.util.Log;
import android.view.MotionEvent;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
@@ -46,8 +47,6 @@
private static final String TAG = "OverviewSwipeController";
- private static final float ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS = 0.1f;
-
// Progress after which the transition is assumed to be a success in case user does not fling
private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
@@ -65,6 +64,7 @@
private float mDisplacementShift;
private float mProgressMultiplier;
private float mEndDisplacement;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private TaskView mTaskBeingDragged;
@@ -93,7 +93,6 @@
@Override
public void onAnimationCancel(Animator animation) {
if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) {
- Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception());
clearState();
}
}
@@ -158,16 +157,16 @@
return mDetector.onTouchEvent(ev);
}
- private boolean reInitAnimationController(boolean goingUp) {
+ private void reInitAnimationController(boolean goingUp) {
if (mCurrentAnimation != null && mCurrentAnimationIsGoingUp == goingUp) {
// No need to init
- return false;
+ return;
}
int scrollDirections = mDetector.getScrollDirections();
if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0)
|| !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) {
// Trying to re-init in an unsupported direction.
- return false;
+ return;
}
if (mCurrentAnimation != null) {
mCurrentAnimation.setPlayFraction(0);
@@ -205,7 +204,6 @@
mCurrentAnimation.getTarget().addListener(this);
mCurrentAnimation.dispatchOnStart();
mProgressMultiplier = 1 / mEndDisplacement;
- return true;
}
@Override
@@ -217,6 +215,7 @@
mDisplacementShift = mCurrentAnimation.getProgressFraction() / mProgressMultiplier;
mCurrentAnimation.pause();
}
+ mFlingBlockCheck.unblockFling();
}
@Override
@@ -226,6 +225,9 @@
totalDisplacement == 0 ? mCurrentAnimationIsGoingUp : totalDisplacement < 0;
if (isGoingUp != mCurrentAnimationIsGoingUp) {
reInitAnimationController(isGoingUp);
+ mFlingBlockCheck.blockFling();
+ } else {
+ mFlingBlockCheck.onEvent();
}
mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier);
return true;
@@ -235,22 +237,14 @@
public void onDragEnd(float velocity, boolean fling) {
final boolean goingToEnd;
final int logAction;
+ boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
+ if (blockedFling) {
+ fling = false;
+ }
if (fling) {
logAction = Touch.FLING;
boolean goingUp = velocity < 0;
- if (goingUp != mCurrentAnimationIsGoingUp) {
- // In case the fling is in opposite direction, make sure if is close enough
- // from the start position
- if (mCurrentAnimation.getProgressFraction()
- >= ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS) {
- // Not allowed
- goingToEnd = false;
- } else {
- goingToEnd = reInitAnimationController(goingUp);
- }
- } else {
- goingToEnd = true;
- }
+ goingToEnd = goingUp == mCurrentAnimationIsGoingUp;
} else {
logAction = Touch.SWIPE;
goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS;
@@ -259,6 +253,9 @@
float progress = mCurrentAnimation.getProgressFraction();
long animationDuration = SwipeDetector.calculateDuration(
velocity, goingToEnd ? (1 - progress) : progress);
+ if (blockedFling && !goingToEnd) {
+ animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity);
+ }
float nextFrameProgress = Utilities.boundToRange(
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index e6030d1..3e80d2c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,6 +16,7 @@
package com.android.launcher3.uioverrides;
+import static android.view.View.VISIBLE;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -201,6 +202,13 @@
return true;
}
+ public static void prepareToShowOverview(Launcher launcher) {
+ RecentsView overview = launcher.getOverviewPanel();
+ if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
+ overview.setAdjacentScale(1.33f);
+ }
+ }
+
private static class LauncherTaskViewController extends TaskViewTouchController<Launcher> {
public LauncherTaskViewController(Launcher activity) {
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index f9dcee0..ae0affe 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -48,6 +48,7 @@
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationProvider;
@@ -99,7 +100,7 @@
RecentsView getVisibleRecentsView();
@UiThread
- boolean switchToRecentsIfVisible();
+ boolean switchToRecentsIfVisible(boolean fromRecentsButton);
Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target);
@@ -120,6 +121,11 @@
*/
LongSwipeHelper getLongSwipeController(T activity, RemoteAnimationTargetSet targetSet);
+ /**
+ * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
+ */
+ int getContainerType();
+
class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
@Override
@@ -277,9 +283,15 @@
}
@Override
- public boolean switchToRecentsIfVisible() {
+ public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
Launcher launcher = getVisibleLaucher();
if (launcher != null) {
+ if (fromRecentsButton) {
+ launcher.getUserEventDispatcher().logActionCommand(
+ LauncherLogProto.Action.Command.RECENTS_BUTTON,
+ getContainerType(),
+ LauncherLogProto.ContainerType.TASKSWITCHER);
+ }
launcher.getStateManager().goToState(OVERVIEW);
return true;
}
@@ -319,6 +331,13 @@
public AlphaProperty getAlphaProperty(Launcher activity) {
return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP);
}
+
+ @Override
+ public int getContainerType() {
+ final Launcher launcher = getVisibleLaucher();
+ return launcher != null ? launcher.getStateManager().getState().containerType
+ : LauncherLogProto.ContainerType.APP;
+ }
}
class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
@@ -457,7 +476,7 @@
}
@Override
- public boolean switchToRecentsIfVisible() {
+ public boolean switchToRecentsIfVisible(boolean fromRecentsButton) {
return false;
}
@@ -495,6 +514,10 @@
return activity.getDragLayer().getAlphaProperty(0);
}
+ @Override
+ public int getContainerType() {
+ return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER;
+ }
}
interface LayoutListener {
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
index edc7457..fbcde8b 100644
--- a/quickstep/src/com/android/quickstep/LongSwipeHelper.java
+++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -26,6 +27,7 @@
import android.view.Surface;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DiscoveryBounce;
@@ -33,7 +35,9 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.FlingBlockCheck;
import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
@@ -44,7 +48,6 @@
*/
public class LongSwipeHelper {
- private static final float MIN_PROGRESS_TO_ALL_APPS = 0.35f;
private static final float SWIPE_DURATION_MULTIPLIER =
Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS));
@@ -53,6 +56,7 @@
private float mMaxSwipeDistance = 1;
private AnimatorPlaybackController mAnimator;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
LongSwipeHelper(Launcher launcher, RemoteAnimationTargetSet targetSet) {
mLauncher = launcher;
@@ -62,6 +66,7 @@
private void init() {
setTargetAlpha(0, true);
+ mFlingBlockCheck.blockFling();
// Init animations
AllAppsTransitionController controller = mLauncher.getAllAppsController();
@@ -74,6 +79,7 @@
public void onMove(float displacement) {
mAnimator.setPlayFraction(displacement / mMaxSwipeDistance);
+ mFlingBlockCheck.onEvent();
}
public void destroy() {
@@ -90,6 +96,11 @@
final boolean toAllApps;
float endProgress;
+ boolean blockedFling = isFling && mFlingBlockCheck.isBlocked();
+ if (blockedFling) {
+ isFling = false;
+ }
+
if (!isFling) {
toAllApps = currentFraction > MIN_PROGRESS_TO_ALL_APPS;
endProgress = toAllApps ? 1 : 0;
@@ -114,7 +125,11 @@
}
}
- mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, isFling, callback));
+ if (blockedFling && !toAllApps) {
+ duration *= LauncherAnimUtils.blockedFlingDurationFactor(0);
+ }
+ final boolean finalIsFling = isFling;
+ mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, finalIsFling, callback));
ValueAnimator animator = mAnimator.getAnimationPlayer();
animator.setDuration(duration).setInterpolator(DEACCEL);
animator.setFloatValues(currentFraction, endProgress);
@@ -150,6 +165,7 @@
mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false);
if (!toAllApps) {
DiscoveryBounce.showForOverviewIfNeeded(mLauncher);
+ mLauncher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(true);
}
mLauncher.getUserEventDispatcher().logStateChangeAction(
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 81a73fc..7b29323 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -52,6 +52,8 @@
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
@@ -224,6 +226,7 @@
private T mActivity;
private RecentsView mRecentsView;
private final long mToggleClickedTime = SystemClock.uptimeMillis();
+ private boolean mUserEventLogged;
public RecentsActivityCommand() {
mHelper = getActivityControlHelper();
@@ -241,7 +244,7 @@
if (!handleCommand(elapsedTime)) {
// Start overview
- if (!mHelper.switchToRecentsIfVisible()) {
+ if (!mHelper.switchToRecentsIfVisible(true)) {
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(overviewIntent, this::createWindowAnimation,
mContext, mMainThreadExecutor.getHandler(), RECENTS_LAUNCH_DURATION);
@@ -284,6 +287,11 @@
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
+ if (!mUserEventLogged) {
+ activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON,
+ mHelper.getContainerType(), ContainerType.TASKSWITCHER);
+ mUserEventLogged = true;
+ }
return false;
}
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index 5ddd904..28b06fb 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -133,7 +133,7 @@
*/
private void breakOutOfQuickScrub() {
if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null
- || !mActivityControlHelper.switchToRecentsIfVisible()) {
+ || !mActivityControlHelper.switchToRecentsIfVisible(false)) {
mActivity.onBackPressed();
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 68432ab..01e5cba 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -345,14 +345,22 @@
private float calculateClearAllButtonAlpha() {
final int childCount = getChildCount();
- if (mShowEmptyMessage || childCount == 0) return 0;
+ if (mShowEmptyMessage || childCount == 0 || mPageScrolls == null
+ || childCount != mPageScrolls.length) {
+ return 0;
+ }
final int scrollEnd = getScrollEnd();
final int oldestChildScroll = getScrollForPage(childCount - 1);
- return Utilities.boundToRange(
- ((float) (getScrollX() - oldestChildScroll)) /
- (scrollEnd - oldestChildScroll), 0, 1);
+ final int clearAllButtonMotionRange = scrollEnd - oldestChildScroll;
+ if (clearAllButtonMotionRange == 0) return 0;
+
+ final float alphaUnbound = ((float) (getScrollX() - oldestChildScroll)) /
+ clearAllButtonMotionRange;
+ if (alphaUnbound > 1) return 0;
+
+ return Math.max(alphaUnbound, 0);
}
private void updateClearAllButtonAlpha() {
@@ -418,7 +426,6 @@
final int requiredChildCount = tasks.size();
for (int i = getChildCount(); i < requiredChildCount; i++) {
final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
- taskView.setOnClickListener(this::onTaskClicked);
addView(taskView);
}
while (getChildCount() > requiredChildCount) {
@@ -444,17 +451,6 @@
onTaskStackUpdated();
}
- private void onTaskClicked(View v) {
- TaskView taskView = (TaskView) v;
- if (taskView.getTask() == null) {
- return;
- }
- taskView.launchTask(true /* animate */);
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- Touch.TAP, Direction.NONE, indexOfChild(taskView),
- TaskUtils.getComponentKeyForTask(taskView.getTask().key));
- }
-
protected void onTaskStackUpdated() { }
public void resetTaskVisuals() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 0ddeae7..82aa45a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -110,6 +110,15 @@
public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ setOnClickListener((view) -> {
+ if (getTask() == null) {
+ return;
+ }
+ launchTask(true /* animate */);
+ BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
+ Touch.TAP, Direction.NONE, ((RecentsView) getParent()).indexOfChild(this),
+ TaskUtils.getComponentKeyForTask(getTask().key));
+ });
setOutlineProvider(new TaskOutlineProvider(getResources()));
}
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 9869fdf..03ffded 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -39,6 +39,9 @@
public static final int SPRING_LOADED_TRANSITION_MS = 150;
public static final int SPRING_LOADED_EXIT_DELAY = 500;
+ // The progress of an animation to all apps must be at least this far along to snap to all apps.
+ public static final float MIN_PROGRESS_TO_ALL_APPS = 0.5f;
+
static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>();
static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
public void onAnimationStart(Animator animation) {
@@ -165,16 +168,8 @@
}
};
- public static final Property<View, Float> ELEVATION =
- new Property<View, Float>(Float.class, "elevation") {
- @Override
- public Float get(View view) {
- return view.getElevation();
- }
-
- @Override
- public void set(View view, Float elevation) {
- view.setElevation(elevation);
- }
- };
+ /** Increase the duration if we prevented the fling, as we are going against a high velocity. */
+ public static int blockedFlingDurationFactor(float velocity) {
+ return (int) Utilities.boundToRange(Math.abs(velocity) / 2, 2f, 6f);
+ }
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 5052674..fbe27b0 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -186,7 +186,7 @@
* translationY factor where 0 is top aligned and 0.5 is centered vertically
*/
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
- return new float[] {1.2f, 0.2f};
+ return new float[] {1.1f, 0f};
}
public void onStateEnabled(Launcher launcher) {
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index cf0c7fc..e6fc4c6 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -16,7 +16,17 @@
package com.android.launcher3;
+import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
+import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import android.animation.Animator;
@@ -237,8 +247,10 @@
// transition plays in reverse and use the same duration as previous state.
mConfig.duration = state == NORMAL ? mState.transitionDuration : state.transitionDuration;
+ AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ prepareForAtomicAnimation(mState, state, builder);
AnimatorSet animation = createAnimationToNewWorkspaceInternal(
- state, new AnimatorSetBuilder(), onCompleteRunnable);
+ state, builder, onCompleteRunnable);
Runnable runnable = new StartAnimRunnable(animation, state.getFinalFocus(mLauncher));
if (delay > 0) {
mUiHandler.postDelayed(runnable, delay);
@@ -248,6 +260,43 @@
}
/**
+ * Prepares for a non-user controlled animation from fromState to toState. Preparations include:
+ * - Setting interpolators for various animations included in the state transition.
+ * - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
+ */
+ public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
+ AnimatorSetBuilder builder) {
+ if (fromState == NORMAL && toState.overviewUi) {
+ builder.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
+ builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
+
+ // Start from a higher overview scale, but only if we're invisible so we don't jump.
+ UiFactory.prepareToShowOverview(mLauncher);
+ } else if (fromState.overviewUi && toState == NORMAL) {
+ builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
+ builder.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
+ builder.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
+ builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+ Workspace workspace = mLauncher.getWorkspace();
+
+ // Start from a higher workspace scale, but only if we're invisible so we don't jump.
+ boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
+ if (isWorkspaceVisible) {
+ CellLayout currentChild = (CellLayout) workspace.getChildAt(
+ workspace.getCurrentPage());
+ isWorkspaceVisible = currentChild.getVisibility() == VISIBLE
+ && currentChild.getShortcutsAndWidgets().getAlpha() > 0;
+ }
+ if (!isWorkspaceVisible) {
+ workspace.setScaleX(0.92f);
+ workspace.setScaleY(0.92f);
+ }
+ }
+ }
+
+ /**
* Creates a {@link AnimatorPlaybackController} that can be used for a controlled
* state transition.
* @param state the final state for the transition.
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index eb816c5..a98867d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -109,7 +109,7 @@
private float mLastMotionXRemainder;
private float mTotalMotionX;
- private int[] mPageScrolls;
+ protected int[] mPageScrolls;
protected final static int TOUCH_STATE_REST = 0;
protected final static int TOUCH_STATE_SCROLLING = 1;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index a03a7a8..2df34d5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1297,7 +1297,9 @@
}
private void updatePageAlphaValues() {
- if (!workspaceInModalState() && !mIsSwitchingState) {
+ // We need to check the isDragging case because updatePageAlphaValues is called between
+ // goToState(SPRING_LOADED) and onStartStateTransition.
+ if (!workspaceInModalState() && !mIsSwitchingState && !mDragController.isDragging()) {
int screenCenter = getScrollX() + getMeasuredWidth() / 2;
for (int i = 0; i < getChildCount(); i++) {
CellLayout child = (CellLayout) getChildAt(i);
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 9f26e4a..e734e70 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -20,6 +20,10 @@
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.HOTSEAT_SEARCH_BOX;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
@@ -30,7 +34,6 @@
import com.android.launcher3.LauncherState.PageAlphaProvider;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
@@ -50,12 +53,13 @@
}
public void setState(LauncherState toState) {
- setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new AnimationConfig());
+ setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(),
+ new AnimationConfig());
}
public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
AnimationConfig config) {
- setWorkspaceProperty(toState, config.getPropertySetter(builder), config);
+ setWorkspaceProperty(toState, config.getPropertySetter(builder), builder, config);
}
public float getFinalScale() {
@@ -66,26 +70,28 @@
* Starts a transition animation for the workspace.
*/
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
- AnimationConfig config) {
+ AnimatorSetBuilder builder, AnimationConfig config) {
float[] scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
mNewScale = scaleAndTranslation[0];
PageAlphaProvider pageAlphaProvider = state.getWorkspacePageAlphaProvider(mLauncher);
final int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
- propertySetter, config);
+ propertySetter, builder, config);
}
-
int elements = state.getVisibleElements(mLauncher);
+ Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
+ pageAlphaProvider.interpolator);
boolean playAtomicComponent = config.playAtomicComponent();
if (playAtomicComponent) {
- propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, Interpolators.ZOOM_OUT);
+ Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
+ propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
propertySetter.setViewAlpha(mLauncher.getHotseat().getLayout(), hotseatIconsAlpha,
- pageAlphaProvider.interpolator);
+ fadeInterpolator);
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
- hotseatIconsAlpha, pageAlphaProvider.interpolator);
+ hotseatIconsAlpha, fadeInterpolator);
}
if (!config.playNonAtomicComponent()) {
@@ -93,43 +99,42 @@
return;
}
- Interpolator translationInterpolator = !playAtomicComponent ? Interpolators.LINEAR
- : Interpolators.ZOOM_OUT;
+ Interpolator translationInterpolator = !playAtomicComponent ? LINEAR : ZOOM_OUT;
propertySetter.setFloat(mWorkspace, View.TRANSLATION_X,
scaleAndTranslation[1], translationInterpolator);
propertySetter.setFloat(mWorkspace, View.TRANSLATION_Y,
scaleAndTranslation[2], translationInterpolator);
propertySetter.setViewAlpha(mLauncher.getHotseatSearchBox(),
- (elements & HOTSEAT_SEARCH_BOX) != 0 ? 1 : 0,
- pageAlphaProvider.interpolator);
+ (elements & HOTSEAT_SEARCH_BOX) != 0 ? 1 : 0, fadeInterpolator);
// Set scrim
WorkspaceAndHotseatScrim scrim = mLauncher.getDragLayer().getScrim();
propertySetter.setFloat(scrim, SCRIM_PROGRESS, state.getWorkspaceScrimAlpha(mLauncher),
- Interpolators.LINEAR);
- propertySetter.setFloat(scrim, SYSUI_PROGRESS, state.hasSysUiScrim ? 1 : 0,
- Interpolators.LINEAR);
+ LINEAR);
+ propertySetter.setFloat(scrim, SYSUI_PROGRESS, state.hasSysUiScrim ? 1 : 0, LINEAR);
}
public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
- NO_ANIM_PROPERTY_SETTER, new AnimationConfig());
+ NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(), new AnimationConfig());
}
private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
- AnimationConfig config) {
+ AnimatorSetBuilder builder, AnimationConfig config) {
float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
if (config.playNonAtomicComponent()) {
propertySetter.setInt(cl.getScrimBackground(),
- DRAWABLE_ALPHA, drawableAlpha, Interpolators.ZOOM_OUT);
+ DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
}
if (config.playAtomicComponent()) {
+ Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
+ pageAlphaProvider.interpolator);
propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
- pageAlpha, pageAlphaProvider.interpolator);
+ pageAlpha, fadeInterpolator);
}
}
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 113571a..2c3e3ee 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -3,6 +3,8 @@
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -128,7 +130,8 @@
// Use a light system UI (dark icons) if all apps is behind at least half of the
// status bar.
- boolean forceChange = shiftCurrent <= mShiftRange / 4;
+ boolean forceChange = shiftCurrent - mScrimView.getDragHandleSize()
+ <= mLauncher.getDeviceProfile().getInsets().top / 2;
if (forceChange) {
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALL_APPS, !mIsDarkTheme);
} else {
@@ -171,7 +174,9 @@
return;
}
- Interpolator interpolator = config.userControlled ? LINEAR : FAST_OUT_SLOW_IN;
+ Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
+ ? builder.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
+ : FAST_OUT_SLOW_IN;
ObjectAnimator anim =
ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, mProgress, targetProgress);
anim.setDuration(config.duration);
diff --git a/src/com/android/launcher3/anim/AnimatorSetBuilder.java b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
index dae2dbc..f10bce8 100644
--- a/src/com/android/launcher3/anim/AnimatorSetBuilder.java
+++ b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
@@ -16,7 +16,6 @@
package com.android.launcher3.anim;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.util.SparseArray;
import android.view.animation.Interpolator;
@@ -32,6 +31,10 @@
public class AnimatorSetBuilder {
public static final int ANIM_VERTICAL_PROGRESS = 0;
+ public static final int ANIM_WORKSPACE_SCALE = 1;
+ public static final int ANIM_WORKSPACE_FADE = 2;
+ public static final int ANIM_OVERVIEW_SCALE = 3;
+ public static final int ANIM_OVERVIEW_FADE = 4;
protected final ArrayList<Animator> mAnims = new ArrayList<>();
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 8374f98..bace7df 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -58,7 +58,7 @@
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
}
- public static final Interpolator OVERSHOOT_0 = new OvershootInterpolator(0);
+ public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 6e48c36..e29250a 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.touch;
+import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -32,6 +33,7 @@
import android.view.MotionEvent;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationComponents;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
@@ -43,6 +45,7 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.TouchController;
@@ -61,8 +64,7 @@
* Play an atomic recents animation when the progress from NORMAL to OVERVIEW reaches this.
*/
public static final float ATOMIC_OVERVIEW_ANIM_THRESHOLD = 0.5f;
- private static final long ATOMIC_NORMAL_TO_OVERVIEW_DURATION = 120;
- private static final long ATOMIC_OVERVIEW_TO_NORMAL_DURATION = 200;
+ protected static final long ATOMIC_DURATION = 200;
protected final Launcher mLauncher;
protected final SwipeDetector mDetector;
@@ -80,7 +82,7 @@
private float mProgressMultiplier;
private float mDisplacementShift;
private boolean mCanBlockFling;
- private boolean mBlockFling;
+ private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
private AnimatorSet mAtomicAnim;
private boolean mPassedOverviewAtomicThreshold;
@@ -210,7 +212,7 @@
mAtomicComponentsStartProgress = mCurrentAnimation.getProgressFraction();
long duration = (long) (getShiftRange() * 2);
mAtomicComponentsController = AnimatorPlaybackController.wrap(
- createAtomicAnimForState(mToState, duration), duration);
+ createAtomicAnimForState(mFromState, mToState, duration), duration);
mAtomicComponentsController.dispatchOnStart();
}
});
@@ -241,7 +243,7 @@
mStartProgress = mCurrentAnimation.getProgressFraction();
}
mCanBlockFling = mFromState == NORMAL;
- mBlockFling = false;
+ mFlingBlockCheck.unblockFling();
}
@Override
@@ -253,16 +255,19 @@
if (progress <= 0) {
if (reinitCurrentAnimation(false, isDragTowardPositive)) {
mDisplacementShift = displacement;
- mBlockFling = mCanBlockFling;
+ if (mCanBlockFling) {
+ mFlingBlockCheck.blockFling();
+ }
}
} else if (progress >= 1) {
if (reinitCurrentAnimation(true, isDragTowardPositive)) {
mDisplacementShift = displacement;
- mBlockFling = mCanBlockFling;
+ if (mCanBlockFling) {
+ mFlingBlockCheck.blockFling();
+ }
}
- } else if (Math.abs(velocity) < SwipeDetector.RELEASE_VELOCITY_PX_MS) {
- // We prevent flinging after passing a state, but allow it if the user pauses briefly.
- mBlockFling = false;
+ } else {
+ mFlingBlockCheck.onEvent();
}
return true;
@@ -289,14 +294,13 @@
: 1f - ATOMIC_OVERVIEW_ANIM_THRESHOLD;
boolean passedThreshold = progress >= threshold;
if (passedThreshold != mPassedOverviewAtomicThreshold) {
- LauncherState targetState = passedThreshold ? toState : fromState;
+ LauncherState atomicFromState = passedThreshold ? fromState: toState;
+ LauncherState atomicToState = passedThreshold ? toState : fromState;
mPassedOverviewAtomicThreshold = passedThreshold;
if (mAtomicAnim != null) {
mAtomicAnim.cancel();
}
- long duration = targetState == OVERVIEW ? ATOMIC_NORMAL_TO_OVERVIEW_DURATION
- : ATOMIC_OVERVIEW_TO_NORMAL_DURATION;
- mAtomicAnim = createAtomicAnimForState(targetState, duration);
+ mAtomicAnim = createAtomicAnimForState(atomicFromState, atomicToState, ATOMIC_DURATION);
mAtomicAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -308,8 +312,10 @@
}
}
- private AnimatorSet createAtomicAnimForState(LauncherState targetState, long duration) {
+ private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
+ long duration) {
AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ mLauncher.getStateManager().prepareForAtomicAnimation(fromState, targetState, builder);
AnimationConfig config = new AnimationConfig();
config.animComponents = ATOMIC_COMPONENT;
config.duration = duration;
@@ -325,7 +331,7 @@
final LauncherState targetState;
final float progress = mCurrentAnimation.getProgressFraction();
- boolean blockedFling = fling && mBlockFling;
+ boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
if (blockedFling) {
fling = false;
}
@@ -338,14 +344,17 @@
// snap to top or bottom using the release velocity
} else {
logAction = Touch.SWIPE;
- targetState = (progress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
+ float successProgress = mToState == ALL_APPS
+ ? MIN_PROGRESS_TO_ALL_APPS : SUCCESS_TRANSITION_PROGRESS;
+ targetState = (progress > successProgress) ? mToState : mFromState;
}
final float endProgress;
final float startProgress;
final long duration;
// Increase the duration if we prevented the fling, as we are going against a high velocity.
- final long durationMultiplier = blockedFling && targetState == mFromState ? 6 : 1;
+ final int durationMultiplier = blockedFling && targetState == mFromState
+ ? LauncherAnimUtils.blockedFlingDurationFactor(velocity) : 1;
if (targetState == mToState) {
endProgress = 1;
diff --git a/src/com/android/launcher3/util/FlingBlockCheck.java b/src/com/android/launcher3/util/FlingBlockCheck.java
new file mode 100644
index 0000000..f9575b9
--- /dev/null
+++ b/src/com/android/launcher3/util/FlingBlockCheck.java
@@ -0,0 +1,52 @@
+/*
+ * 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.launcher3.util;
+
+import android.os.SystemClock;
+
+/**
+ * Determines whether a fling should be blocked. Currently we block flings when crossing thresholds
+ * to new states, and unblock after a short duration.
+ */
+public class FlingBlockCheck {
+ // Allow flinging to a new state after waiting this many milliseconds.
+ private static final long UNBLOCK_FLING_PAUSE_DURATION = 200;
+
+ private boolean mBlockFling;
+ private long mBlockFlingTime;
+
+ public void blockFling() {
+ mBlockFling = true;
+ mBlockFlingTime = SystemClock.uptimeMillis();
+ }
+
+ public void unblockFling() {
+ mBlockFling = false;
+ mBlockFlingTime = 0;
+ }
+
+ public void onEvent() {
+ // We prevent flinging after passing a state, but allow it if the user pauses briefly.
+ if (SystemClock.uptimeMillis() - mBlockFlingTime >= UNBLOCK_FLING_PAUSE_DURATION) {
+ mBlockFling = false;
+ }
+ }
+
+ public boolean isBlocked() {
+ return mBlockFling;
+ }
+}
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 49e96be..6bbce00 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -397,4 +397,8 @@
return false;
}
}
+
+ public int getDragHandleSize() {
+ return mDragHandleSize;
+ }
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index e9a47a7..e93dd5a 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -55,4 +55,5 @@
return false;
}
+ public static void prepareToShowOverview(Launcher launcher) { }
}