summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/values/config.xml9
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java4
-rw-r--r--src/com/android/launcher3/CellLayout.java17
-rw-r--r--src/com/android/launcher3/Launcher.java94
-rw-r--r--src/com/android/launcher3/LauncherAnimUtils.java24
-rw-r--r--src/com/android/launcher3/LauncherModel.java2
-rw-r--r--src/com/android/launcher3/LauncherStateTransitionAnimation.java157
-rw-r--r--src/com/android/launcher3/PinchAnimationManager.java19
-rw-r--r--src/com/android/launcher3/Workspace.java148
-rw-r--r--src/com/android/launcher3/WorkspaceStateTransitionAnimation.java426
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java26
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java5
-rw-r--r--src/com/android/launcher3/dragndrop/DragLayer.java55
-rw-r--r--src/com/android/launcher3/dragndrop/PageCutOutScrimDrawable.java90
-rw-r--r--src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java6
-rw-r--r--src/com/android/launcher3/folder/Folder.java5
-rw-r--r--src/com/android/launcher3/folder/FolderAnimationManager.java18
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java4
-rw-r--r--src/com/android/launcher3/logging/UserEventDispatcher.java8
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java12
-rw-r--r--src/com/android/launcher3/util/FlingAnimation.java4
-rw-r--r--src/com/android/launcher3/widget/BaseWidgetSheet.java13
-rw-r--r--src/com/android/launcher3/widget/WidgetsBottomSheet.java5
-rw-r--r--src/com/android/launcher3/widget/WidgetsFullSheet.java5
24 files changed, 520 insertions, 636 deletions
diff --git a/res/values/config.xml b/res/values/config.xml
index 27d4655b9..c0bf36038 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -46,20 +46,13 @@
<!-- AllApps & Launcher transitions -->
<!-- The alpha of the AppsCustomize bg in spring loaded mode -->
- <integer name="config_workspaceScrimAlpha">30</integer>
- <integer name="config_allAppsTransitionTime">100</integer>
- <integer name="config_overviewTransitionTime">250</integer>
+ <integer name="config_workspaceScrimAlpha">76</integer>
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
<integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
<!-- Out of 100, the percent to shrink the workspace during overview mode. -->
<integer name="config_workspaceOverviewShrinkPercentage">70</integer>
- <!-- Fade/zoom in/out duration & scale in a Launcher overlay transition.
- Note: This should be less than the config_overlayTransitionTime as they happen together. -->
- <integer name="config_overlaySlideRevealTime">320</integer>
- <integer name="config_overlayTransitionTime">300</integer>
-
<!-- This constant stores the ratio of the all apps button drawable which
is used for internal (baked-in) padding -->
<integer name="config_allAppsButtonPaddingPercent">17</integer>
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index e1b5e2c75..1a1c3198f 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+
import android.animation.AnimatorSet;
import android.animation.FloatArrayEvaluator;
import android.animation.ObjectAnimator;
@@ -229,7 +231,7 @@ public abstract class ButtonDropTarget extends TextView
public void run() {
completeDrop(d);
mDropTargetBar.onDragEnd();
- mLauncher.exitSpringLoadedDragMode(true, 0);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
}
};
dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index d6c8575d6..3643971a4 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -104,8 +104,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
private final ArrayList<PreviewBackground> mFolderBackgrounds = new ArrayList<>();
final PreviewBackground mFolderLeaveBehind = new PreviewBackground();
- private float mBackgroundAlpha;
-
private static final int[] BACKGROUND_STATE_ACTIVE = new int[] { android.R.attr.state_active };
private static final int[] BACKGROUND_STATE_DEFAULT = new int[0];
private final Drawable mBackground;
@@ -221,7 +219,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mBackground = res.getDrawable(R.drawable.bg_celllayout);
mBackground.setCallback(this);
- mBackground.setAlpha((int) (mBackgroundAlpha * 255));
+ mBackground.setAlpha(0);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * grid.iconSizePx);
@@ -440,7 +438,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
// When we're small, we are either drawn normally or in the "accepts drops" state (during
// a drag). However, we also drag the mini hover background *over* one of those two
// backgrounds
- if (mBackgroundAlpha > 0.0f) {
+ if (mBackground.getAlpha() > 0) {
mBackground.draw(canvas);
}
@@ -847,15 +845,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
return getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth);
}
- public float getBackgroundAlpha() {
- return mBackgroundAlpha;
- }
-
- public void setBackgroundAlpha(float alpha) {
- if (mBackgroundAlpha != alpha) {
- mBackgroundAlpha = alpha;
- mBackground.setAlpha((int) (mBackgroundAlpha * 255));
- }
+ public Drawable getScrimBackground() {
+ return mBackground;
}
@Override
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bfcd82ace..a80e62b08 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,6 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_SHORT_TIMEOUT;
+import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_APPS;
import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_WIDGETS;
@@ -117,6 +120,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ActivityResultInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -205,15 +209,13 @@ public class Launcher extends BaseActivity
static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";
/** The different states that Launcher can be in. */
- enum State { WORKSPACE, WORKSPACE_SPRING_LOADED, APPS, APPS_SPRING_LOADED,
- WIDGETS, WIDGETS_SPRING_LOADED }
+ enum State { WORKSPACE, WORKSPACE_SPRING_LOADED, APPS}
@Thunk State mState = State.WORKSPACE;
@Thunk LauncherStateTransitionAnimation mStateTransitionAnimation;
private boolean mIsSafeModeEnabled;
- public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 500;
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
// How long to wait before the new-shortcut animation automatically pans the workspace
@@ -366,9 +368,6 @@ public class Launcher extends BaseActivity
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this);
- if (Utilities.ATLEAST_MARSHMALLOW) {
- mAppWidgetHost.addProviderChangeListener(this);
- }
mAppWidgetHost.startListening();
// If we are getting an onCreate, we can actually preempt onResume and unset mPaused here,
@@ -582,8 +581,7 @@ public class Launcher extends BaseActivity
Runnable exitSpringLoaded = new Runnable() {
@Override
public void run() {
- exitSpringLoadedDragMode((resultCode != RESULT_CANCELED),
- EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
}
};
@@ -635,7 +633,7 @@ public class Launcher extends BaseActivity
final Runnable onComplete = new Runnable() {
@Override
public void run() {
- exitSpringLoadedDragMode(false, 0);
+ exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
}
};
@@ -763,8 +761,7 @@ public class Launcher extends BaseActivity
@Override
public void run() {
completeAddAppWidget(appWidgetId, requestArgs, layout, null);
- exitSpringLoadedDragMode((resultCode != RESULT_CANCELED),
- EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
}
};
} else if (resultCode == RESULT_CANCELED) {
@@ -1439,8 +1436,9 @@ public class Launcher extends BaseActivity
if (topOpenView != null) {
topOpenView.logActionCommand(Action.Command.HOME_INTENT);
} else if (alreadyOnHome) {
- ued.logActionCommand(Action.Command.HOME_INTENT,
- mWorkspace.getState().containerType, mWorkspace.getCurrentPage());
+ Target target = newContainerTarget(mWorkspace.getState().containerType);
+ target.pageIndex = mWorkspace.getCurrentPage();
+ ued.logActionCommand(Action.Command.HOME_INTENT, target);
}
// In all these cases, only animate if we're already on home
@@ -1714,8 +1712,7 @@ public class Launcher extends BaseActivity
@Override
public void run() {
// Exit spring loaded mode if necessary after adding the widget
- exitSpringLoadedDragMode(true, EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT
- );
+ exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
}
};
completeAddAppWidget(appWidgetId, info, boundWidget, addFlowHandler.getProviderInfo(this));
@@ -1899,9 +1896,6 @@ public class Launcher extends BaseActivity
} else if (isAppsViewVisible()) {
ued.logActionCommand(Action.Command.BACK, ContainerType.ALLAPPS);
showWorkspace(true);
- } else if (isWidgetsViewVisible()) {
- ued.logActionCommand(Action.Command.BACK, ContainerType.WIDGETS);
- showOverviewMode(true);
} else if (mWorkspace.isInOverviewMode()) {
ued.logActionCommand(Action.Command.BACK, ContainerType.OVERVIEW);
showWorkspace(true);
@@ -2444,10 +2438,6 @@ public class Launcher extends BaseActivity
return mState == State.APPS;
}
- public boolean isWidgetsViewVisible() {
- return mState == State.WIDGETS;
- }
-
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
@@ -2546,29 +2536,18 @@ public class Launcher extends BaseActivity
/**
* Shows the apps view.
- */
- public void showAppsView(boolean animated) {
- markAppsViewShown();
- showAppsOrWidgets(State.APPS, animated);
- }
-
- /**
- * Sets up the transition to show the apps/widgets view.
*
* @return whether the current from and to state allowed this operation
*/
// TODO: calling method should use the return value so that when {@code false} is returned
// the workspace transition doesn't fall into invalid state.
- private boolean showAppsOrWidgets(State toState, boolean animated) {
+ public boolean showAppsView(boolean animated) {
+ markAppsViewShown();
+
if (!(mState == State.WORKSPACE ||
- mState == State.APPS_SPRING_LOADED ||
- mState == State.WIDGETS_SPRING_LOADED ||
(mState == State.APPS && mAllAppsController.isTransitioning()))) {
return false;
}
- if (toState != State.APPS && toState != State.WIDGETS) {
- return false;
- }
// This is a safe and supported transition to bypass spring_loaded mode.
if (mExitSpringLoadedModeRunnable != null) {
@@ -2576,14 +2555,10 @@ public class Launcher extends BaseActivity
mExitSpringLoadedModeRunnable = null;
}
- if (toState == State.APPS) {
- mStateTransitionAnimation.startAnimationToAllApps(animated);
- } else {
- mStateTransitionAnimation.startAnimationToWidgets(animated);
- }
+ mStateTransitionAnimation.startAnimationToAllApps(animated);
// Change the state *after* we've called all the transition code
- setState(toState);
+ setState(State.APPS);
AbstractFloatingView.closeAllOpenViews(this);
// Send an accessibility event to announce the context change
@@ -2613,12 +2588,11 @@ public class Launcher extends BaseActivity
setState(State.WORKSPACE_SPRING_LOADED);
}
- public void exitSpringLoadedDragMode(final boolean successfulDrop, int delay) {
- exitSpringLoadedDragMode(successfulDrop, delay, null);
+ public void exitSpringLoadedDragMode(int delay) {
+ exitSpringLoadedDragMode(delay, null);
}
- public void exitSpringLoadedDragMode(final boolean successfulDrop, int delay,
- final Runnable onCompleteRunnable) {
+ public void exitSpringLoadedDragMode(int delay, final Runnable onCompleteRunnable) {
if (!isStateSpringLoaded()) return;
// Unlock rotation lock
@@ -2634,18 +2608,12 @@ public class Launcher extends BaseActivity
mExitSpringLoadedModeRunnable = new Runnable() {
@Override
public void run() {
- if (successfulDrop) {
- // TODO(hyunyoungs): verify if this hack is still needed, if not, delete.
- //
- // Before we show workspace, hide all apps again because
- // exitSpringLoadedDragMode made it visible. This is a bit hacky; we should
- // clean up our state transition functions
- showWorkspace(true, onCompleteRunnable);
- } else if (mState == State.APPS_SPRING_LOADED) {
- showAppsView(true /* animated */);
- } else if (mState == State.WORKSPACE_SPRING_LOADED) {
- showWorkspace(true);
- }
+ // TODO(hyunyoungs): verify if this hack is still needed, if not, delete.
+ //
+ // Before we show workspace, hide all apps again because
+ // exitSpringLoadedDragMode made it visible. This is a bit hacky; we should
+ // clean up our state transition functions
+ showWorkspace(true, onCompleteRunnable);
mExitSpringLoadedModeRunnable = null;
}
};
@@ -2653,8 +2621,7 @@ public class Launcher extends BaseActivity
}
boolean isStateSpringLoaded() {
- return mState == State.WORKSPACE_SPRING_LOADED || mState == State.APPS_SPRING_LOADED
- || mState == State.WIDGETS_SPRING_LOADED;
+ return mState == State.WORKSPACE_SPRING_LOADED;
}
@Override
@@ -3397,13 +3364,6 @@ public class Launcher extends BaseActivity
}
}
- @Override
- public void notifyWidgetProvidersChanged() {
- if (mWorkspace.getState().shouldUpdateWidget) {
- refreshAndBindWidgetsForPackageUser(null);
- }
- }
-
/**
* @param packageUser if null, refreshes all widgets and shortcuts, otherwise only
* refreshes the widgets and shortcuts associated with the given package/user
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index cfb9b570b..02f05c30e 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -30,6 +30,16 @@ import java.util.HashSet;
import java.util.WeakHashMap;
public class LauncherAnimUtils {
+ /**
+ * Durations for various state animations. These are not defined in resources to allow
+ * easier access from static classes and enums
+ */
+ public static final int ALL_APPS_TRANSITION_MS = 320;
+ public static final int OVERVIEW_TRANSITION_MS = 250;
+ public static final int SPRING_LOADED_TRANSITION_MS = 150;
+ public static final int SPRING_LOADED_EXIT_SHORT_TIMEOUT = 500;
+ public static final int SPRING_LOADED_EXIT_NEXT_FRAME = 0;
+
static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>();
static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
public void onAnimationStart(Animator animation) {
@@ -141,4 +151,18 @@ public class LauncherAnimUtils {
drawable.setAlpha(alpha);
}
};
+
+ public static final Property<View, Float> SCALE_PROPERTY =
+ new Property<View, Float>(Float.class, "scale") {
+ @Override
+ public Float get(View view) {
+ return view.getScaleX();
+ }
+
+ @Override
+ public void set(View view, Float scale) {
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ }
+ };
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 618bd0f73..469c5f1c0 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -134,7 +134,7 @@ public class LauncherModel extends BroadcastReceiver
}
};
- public interface Callbacks extends LauncherAppWidgetHost.ProviderChangedListener {
+ public interface Callbacks {
public boolean setLoadOnResume();
public int getCurrentWorkspaceScreen();
public void clearPendingBinds();
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
index 5823734e4..9c83e3c01 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java
@@ -19,7 +19,6 @@ package com.android.launcher3;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.content.res.Resources;
import android.util.Log;
import android.view.View;
@@ -74,6 +73,7 @@ public class LauncherStateTransitionAnimation {
public static final String TAG = "LSTAnimation";
+ private final AnimationConfig mConfig = new AnimationConfig();
@Thunk Launcher mLauncher;
@Thunk AnimatorSet mCurrentAnimation;
AllAppsTransitionController mAllAppsController;
@@ -86,24 +86,22 @@ public class LauncherStateTransitionAnimation {
/**
* Starts an animation to the apps view.
*/
- public void startAnimationToAllApps(final boolean animated) {
+ public void startAnimationToAllApps(boolean animated) {
final AllAppsContainerView toView = mLauncher.getAppsView();
+ // If for some reason our views aren't initialized, don't animate
+ animated = animated && (toView != null);
+
final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
- final Resources res = mLauncher.getResources();
- final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
final AnimationLayerSet layerViews = new AnimationLayerSet();
- // If for some reason our views aren't initialized, don't animate
- boolean initialized = toView != null;
-
// Cancel the current animation
cancelAnimation();
- playCommonTransitionAnimations(Workspace.State.NORMAL_HIDDEN,
- animated, initialized, animation, layerViews);
- if (!animated || !initialized) {
+ if (!animated) {
+ mLauncher.getWorkspace().setState(Workspace.State.NORMAL_HIDDEN);
+
mAllAppsController.finishPullUp();
toView.setTranslationX(0.0f);
toView.setTranslationY(0.0f);
@@ -115,6 +113,7 @@ public class LauncherStateTransitionAnimation {
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
return;
}
+
if (!FeatureFlags.LAUNCHER3_PHYSICS) {
// We are animating the content view alpha, so ensure we have a layer for it.
layerViews.addView(toView);
@@ -127,12 +126,16 @@ public class LauncherStateTransitionAnimation {
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
}
});
- boolean shouldPost = mAllAppsController.animateToAllApps(animation, revealDurationSlide);
+
+ mConfig.reset();
+ mAllAppsController.animateToAllApps(animation, mConfig);
+ mLauncher.getWorkspace().setStateWithAnimation(Workspace.State.NORMAL_HIDDEN,
+ layerViews, animation, mConfig);
Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
mCurrentAnimation = animation;
mCurrentAnimation.addListener(layerViews);
- if (shouldPost) {
+ if (mConfig.shouldPost) {
toView.post(startAnimRunnable);
} else {
startAnimRunnable.run();
@@ -140,14 +143,6 @@ public class LauncherStateTransitionAnimation {
}
/**
- * Starts an animation to the widgets view.
- */
- public void startAnimationToWidgets(final boolean animated) {
- // TODO: Remove this
- throw new RuntimeException("This cannot happen");
- }
-
- /**
* Starts an animation to the workspace from the current overlay view.
*/
public void startAnimationToWorkspace(final Launcher.State fromState,
@@ -159,8 +154,7 @@ public class LauncherStateTransitionAnimation {
Log.e(TAG, "Unexpected call to startAnimationToWorkspace");
}
- if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED
- || mAllAppsController.isTransitioning()) {
+ if (fromState == Launcher.State.APPS || mAllAppsController.isTransitioning()) {
startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState,
animated, onCompleteRunnable);
} else {
@@ -170,54 +164,27 @@ public class LauncherStateTransitionAnimation {
}
/**
- * Plays animations used by various transitions.
- */
- private void playCommonTransitionAnimations(
- Workspace.State toWorkspaceState,
- boolean animated, boolean initialized, AnimatorSet animation,
- AnimationLayerSet layerViews) {
- // Create the workspace animation.
- // NOTE: this call apparently also sets the state for the workspace if !animated
- Animator workspaceAnim = mLauncher.getWorkspace().
- setStateWithAnimation(toWorkspaceState, animated, layerViews);
-
- if (animated && initialized) {
- // Play the workspace animation
- if (workspaceAnim != null) {
- animation.play(workspaceAnim);
- }
- }
- }
-
- /**
* Starts an animation to the workspace from the apps view.
*/
private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState,
- final Workspace.State toWorkspaceState, final boolean animated,
+ final Workspace.State toWorkspaceState, boolean animated,
final Runnable onCompleteRunnable) {
-
final AllAppsContainerView fromView = mLauncher.getAppsView();
- final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
- final Resources res = mLauncher.getResources();
- final int revealDurationSlide = res.getInteger(R.integer.config_overlaySlideRevealTime);
-
- final View toView = mLauncher.getWorkspace();
+ // If for some reason our views aren't initialized, don't animate
+ animated = animated & (fromView != null);
+ final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
final AnimationLayerSet layerViews = new AnimationLayerSet();
- // If for some reason our views aren't initialized, don't animate
- boolean initialized = fromView != null;
-
// Cancel the current animation
cancelAnimation();
- playCommonTransitionAnimations(toWorkspaceState,
- animated, initialized, animation, layerViews);
- if (!animated || !initialized) {
+ if (!animated) {
if (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
mAllAppsController.finishPullDown();
}
fromView.setVisibility(View.GONE);
+ mLauncher.getWorkspace().setState(toWorkspaceState);
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
// Run any queued runnables
@@ -227,9 +194,6 @@ public class LauncherStateTransitionAnimation {
return;
}
- // We are animating the content view alpha, so ensure we have a layer for it
- layerViews.addView(toView);
-
animation.addListener(new AnimatorListenerAdapter() {
boolean canceled = false;
@Override
@@ -250,12 +214,16 @@ public class LauncherStateTransitionAnimation {
}
});
- boolean shouldPost = mAllAppsController.animateToWorkspace(animation, revealDurationSlide);
- Runnable startAnimRunnable = new StartAnimRunnable(animation, toView);
+ mConfig.reset();
+ mAllAppsController.animateToWorkspace(animation, mConfig);
+ mLauncher.getWorkspace().setStateWithAnimation(toWorkspaceState, layerViews, animation,
+ mConfig);
+
+ Runnable startAnimRunnable = new StartAnimRunnable(animation, mLauncher.getWorkspace());
mCurrentAnimation = animation;
mCurrentAnimation.addListener(layerViews);
- if (shouldPost) {
+ if (mConfig.shouldPost) {
fromView.post(startAnimRunnable);
} else {
startAnimRunnable.run();
@@ -269,39 +237,41 @@ public class LauncherStateTransitionAnimation {
final Workspace.State toWorkspaceState, final boolean animated,
final Runnable onCompleteRunnable) {
final View fromWorkspace = mLauncher.getWorkspace();
- final AnimationLayerSet layerViews = new AnimationLayerSet();
- final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
-
// Cancel the current animation
cancelAnimation();
- playCommonTransitionAnimations(toWorkspaceState, animated, animated, animation, layerViews);
mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
- if (animated) {
- animation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Run any queued runnables
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
-
- // This can hold unnecessary references to views.
- cleanupAnimation();
- }
- });
- animation.addListener(layerViews);
- fromWorkspace.post(new StartAnimRunnable(animation, null));
- mCurrentAnimation = animation;
- } else /* if (!animated) */ {
+ if (!animated) {
+ mLauncher.getWorkspace().setState(toWorkspaceState);
// Run any queued runnables
if (onCompleteRunnable != null) {
onCompleteRunnable.run();
}
-
- mCurrentAnimation = null;
+ return;
}
+
+ final AnimationLayerSet layerViews = new AnimationLayerSet();
+ final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
+ mConfig.reset();
+ mLauncher.getWorkspace().setStateWithAnimation(toWorkspaceState,
+ layerViews, animation, mConfig);
+
+ animation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Run any queued runnables
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+
+ // This can hold unnecessary references to views.
+ cleanupAnimation();
+ }
+ });
+ animation.addListener(layerViews);
+ fromWorkspace.post(new StartAnimRunnable(animation, null));
+ mCurrentAnimation = animation;
}
/**
@@ -340,4 +310,23 @@ public class LauncherStateTransitionAnimation {
mAnim.start();
}
}
+
+ public static class AnimationConfig {
+ public boolean shouldPost;
+
+ private long mOverriddenDuration = -1;
+
+ public void reset() {
+ shouldPost = false;
+ mOverriddenDuration = -1;
+ }
+
+ public void overrideDuration(long duration) {
+ mOverriddenDuration = duration;
+ }
+
+ public long getDuration(long defaultDuration) {
+ return mOverriddenDuration >= 0 ? mOverriddenDuration : defaultDuration;
+ }
+ }
}
diff --git a/src/com/android/launcher3/PinchAnimationManager.java b/src/com/android/launcher3/PinchAnimationManager.java
index c3d3bb3df..10f35bde3 100644
--- a/src/com/android/launcher3/PinchAnimationManager.java
+++ b/src/com/android/launcher3/PinchAnimationManager.java
@@ -75,8 +75,7 @@ public class PinchAnimationManager {
mOverviewScale = mWorkspace.getOverviewModeShrinkFactor();
mOverviewTranslationY = mWorkspace.getOverviewModeTranslationY();
- mNormalOverviewTransitionDuration = mWorkspace.getStateTransitionAnimation()
- .mOverviewTransitionTime;
+ mNormalOverviewTransitionDuration = LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
}
public int getNormalOverviewTransitionDuration() {
@@ -131,7 +130,8 @@ public class PinchAnimationManager {
mWorkspace.setScaleX(interpolatedScale);
mWorkspace.setScaleY(interpolatedScale);
mWorkspace.setTranslationY(interpolatedTranslationY);
- setOverviewPanelsAlpha(1f - interpolatedProgress, 0);
+ int alpha = (int) ((1f - interpolatedProgress) * 255);
+ setOverviewPanelsAlpha(alpha, 0);
}
/**
@@ -180,14 +180,15 @@ public class PinchAnimationManager {
}
}
- private void setOverviewPanelsAlpha(float alpha, int duration) {
+ private void setOverviewPanelsAlpha(int alpha, int duration) {
int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
if (duration == 0) {
- cl.setBackgroundAlpha(alpha);
+ cl.getScrimBackground().setAlpha(alpha);
} else {
- ObjectAnimator.ofFloat(cl, "backgroundAlpha", alpha).setDuration(duration).start();
+ ObjectAnimator.ofInt(cl.getScrimBackground(),
+ LauncherAnimUtils.DRAWABLE_ALPHA, alpha).setDuration(duration).start();
}
}
}
@@ -202,9 +203,9 @@ public class PinchAnimationManager {
}
private void animateScrim(boolean show) {
- float endValue = show ? mWorkspace.getStateTransitionAnimation().mWorkspaceScrimAlpha : 0;
- startAnimator(INDEX_SCRIM,
- ObjectAnimator.ofFloat(mLauncher.getDragLayer(), "backgroundAlpha", endValue),
+ int endValue = show ? mWorkspace.getStateTransitionAnimation().mWorkspaceScrimAlpha : 0;
+ startAnimator(INDEX_SCRIM, ObjectAnimator.ofInt(
+ mLauncher.getDragLayer().getScrim(), LauncherAnimUtils.DRAWABLE_ALPHA, endValue),
mNormalOverviewTransitionDuration);
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 1525e41d2..b57ce6375 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -16,6 +16,12 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_SHORT_TIMEOUT;
+import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
+import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -49,12 +55,14 @@ import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.Toast;
import com.android.launcher3.Launcher.LauncherOverlay;
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
+import com.android.launcher3.LauncherStateTransitionAnimation.AnimationConfig;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
@@ -181,20 +189,26 @@ public class Workspace extends PagedView
// in all apps or customize mode)
public enum State {
- NORMAL (false, false, ContainerType.WORKSPACE),
- NORMAL_HIDDEN (false, false, ContainerType.ALLAPPS),
- SPRING_LOADED (false, true, ContainerType.WORKSPACE),
- OVERVIEW (true, true, ContainerType.OVERVIEW),
- OVERVIEW_HIDDEN (true, false, ContainerType.WIDGETS);
+ NORMAL (false, ContainerType.WORKSPACE, false, 1, 0),
+ NORMAL_HIDDEN (false, ContainerType.ALLAPPS, false, 1, ALL_APPS_TRANSITION_MS),
+ SPRING_LOADED (true, ContainerType.WORKSPACE, true, 1, SPRING_LOADED_TRANSITION_MS),
+ OVERVIEW (true, ContainerType.OVERVIEW, true, 0, OVERVIEW_TRANSITION_MS);
- public final boolean shouldUpdateWidget;
public final boolean hasMultipleVisiblePages;
public final int containerType;
- State(boolean shouldUpdateWidget, boolean hasMultipleVisiblePages, int containerType) {
- this.shouldUpdateWidget = shouldUpdateWidget;
+ // Properties related to state transition animation.
+ public final boolean hasScrim;
+ public final float hotseatAlpha;
+ public final int transitionDuration;
+
+ State(boolean hasMultipleVisiblePages, int containerType,
+ boolean hasScrim, float hotseatAlpha, int transitionDuration) {
this.hasMultipleVisiblePages = hasMultipleVisiblePages;
this.containerType = containerType;
+ this.hasScrim = hasScrim;
+ this.hotseatAlpha = hotseatAlpha;
+ this.transitionDuration = transitionDuration;
}
}
@@ -1296,9 +1310,7 @@ public class Workspace extends PagedView
}
});
- AccessibilityManager am = (AccessibilityManager)
- mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
- final boolean accessibilityEnabled = am.isEnabled();
+ final boolean accessibilityEnabled = isAccessibilityEnabled();
animator.addUpdateListener(
new AlphaUpdateListener(mLauncher.getHotseat(), accessibilityEnabled));
animator.addUpdateListener(
@@ -1307,6 +1319,12 @@ public class Workspace extends PagedView
}
}
+ protected boolean isAccessibilityEnabled() {
+ AccessibilityManager am = (AccessibilityManager)
+ mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ return am.isEnabled();
+ }
+
@Override
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
@@ -1562,7 +1580,7 @@ public class Workspace extends PagedView
}
public void snapToPageFromOverView(int whichPage) {
- mStateTransitionAnimation.snapToPageFromOverView(whichPage);
+ snapToPage(whichPage, OVERVIEW_TRANSITION_MS, new ZoomInInterpolator());
}
int getOverviewModeTranslationY() {
@@ -1606,45 +1624,42 @@ public class Workspace extends PagedView
return mOverviewModeShrinkFactor;
}
+
/**
- * Sets the current workspace {@link State}, returning an animation transitioning the workspace
- * to that new state.
+ * Sets the current workspace {@link State} and updates the UI without any animations
*/
- public Animator setStateWithAnimation(State toState, boolean animated,
- AnimationLayerSet layerViews) {
- final State fromState = mState;
-
+ public void setState(State toState) {
// Update the current state
mState = toState;
-
- // Create the animation to the new state
- AnimatorSet workspaceAnim = mStateTransitionAnimation.getAnimationToState(fromState,
- toState, animated, layerViews);
-
- boolean shouldNotifyWidgetChange = !fromState.shouldUpdateWidget
- && toState.shouldUpdateWidget;
+ mStateTransitionAnimation.setState(mState);
updateAccessibilityFlags();
+ onPrepareStateTransition(mState.hasMultipleVisiblePages);
+ onStartStateTransition();
+ onEndStateTransition();
+ }
- if (shouldNotifyWidgetChange) {
- mLauncher.notifyWidgetProvidersChanged();
- }
+ /**
+ * Sets the current workspace {@link State}, while animating the UI
+ */
+ public void setStateWithAnimation(State toState, AnimationLayerSet layerViews, AnimatorSet anim,
+ AnimationConfig config) {
+ final State fromState = mState;
+ // Update the current state
+ mState = toState;
+ mStateTransitionAnimation.setStateWithAnimation(
+ fromState, toState, anim, layerViews, config);
+
+ updateAccessibilityFlags();
onPrepareStateTransition(mState.hasMultipleVisiblePages);
StateTransitionListener listener = new StateTransitionListener();
- if (animated) {
- ValueAnimator stepAnimator = ValueAnimator.ofFloat(0, 1);
- stepAnimator.addUpdateListener(listener);
-
- workspaceAnim.play(stepAnimator);
- workspaceAnim.addListener(listener);
- } else {
- listener.onAnimationStart(null);
- listener.onAnimationEnd(null);
- }
+ ValueAnimator stepAnimator = ValueAnimator.ofFloat(0, 1);
+ stepAnimator.addUpdateListener(listener);
- return workspaceAnim;
+ anim.play(stepAnimator);
+ anim.addListener(listener);
}
public State getState() {
@@ -1701,11 +1716,31 @@ public class Workspace extends PagedView
updateChildrenLayersEnabled();
}
+ private void onStartStateTransition() {
+ if (mState == State.SPRING_LOADED) {
+ // Show the page indicator at the same time as the rest of the transition.
+ showPageIndicatorAtCurrentScroll();
+ }
+ getPageIndicator().setShouldAutoHide(mState != State.SPRING_LOADED);
+ }
+
public void onEndStateTransition() {
mIsSwitchingState = false;
updateChildrenLayersEnabled();
mForceDrawAdjacentPages = false;
mTransitionProgress = 1;
+
+ if (mState == State.OVERVIEW) {
+ enableFreeScroll();
+ } else {
+ disableFreeScroll();
+ }
+
+ ViewGroup overviewPanel = mLauncher.getOverviewPanel();
+ if (isAccessibilityEnabled() && overviewPanel.getVisibility() == View.VISIBLE) {
+ overviewPanel.getChildAt(0).performAccessibilityAction(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ }
}
public void startDrag(CellLayout.CellInfo cellInfo, DragOptions options) {
@@ -2076,8 +2111,7 @@ public class Workspace extends PagedView
dropTargetLayout, mTargetCell, distance, false, d.dragView) ||
addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
distance, d, false)) {
- mLauncher.exitSpringLoadedDragMode(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
return;
}
@@ -2191,9 +2225,8 @@ public class Workspace extends PagedView
// Animate the item to its original position, while simultaneously exiting
// spring-loaded mode so the page meets the icon where it was picked up.
mLauncher.getDragController().animateDragViewToOriginalPosition(
- onCompleteRunnable, cell,
- mStateTransitionAnimation.mSpringLoadedTransitionTime);
- mLauncher.exitSpringLoadedDragMode(false, 0);
+ onCompleteRunnable, cell, SPRING_LOADED_TRANSITION_MS);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
mLauncher.getDropTargetBar().onDragEnd();
parent.onDropChild(cell);
return;
@@ -2216,8 +2249,8 @@ public class Workspace extends PagedView
}
parent.onDropChild(cell);
- mLauncher.exitSpringLoadedDragMode(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, onCompleteRunnable);
+ mLauncher.exitSpringLoadedDragMode(
+ SPRING_LOADED_EXIT_SHORT_TIMEOUT, onCompleteRunnable);
}
if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
@@ -2824,8 +2857,7 @@ public class Workspace extends PagedView
animationStyle, finalView, true);
} else {
// This is for other drag/drop cases, like dragging from All Apps
- mLauncher.exitSpringLoadedDragMode(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
View view;
@@ -2887,10 +2919,9 @@ public class Workspace extends PagedView
// We wrap the animation call in the temporary set and reset of the current
// cellLayout to its final transform -- this means we animate the drag view to
// the correct final location.
- setFinalTransitionTransform(cellLayout);
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view,
- this);
- resetTransitionTransform(cellLayout);
+ setFinalTransitionTransform();
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view, this);
+ resetTransitionTransform();
}
}
}
@@ -2926,10 +2957,10 @@ public class Workspace extends PagedView
loc[0] = r.left;
loc[1] = r.top;
- setFinalTransitionTransform(layout);
+ setFinalTransitionTransform();
float cellLayoutScale =
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc, true);
- resetTransitionTransform(layout);
+ resetTransitionTransform();
if (scale) {
float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
@@ -3013,14 +3044,14 @@ public class Workspace extends PagedView
}
}
- public void setFinalTransitionTransform(CellLayout layout) {
+ public void setFinalTransitionTransform() {
if (isSwitchingState()) {
mCurrentScale = getScaleX();
setScaleX(mStateTransitionAnimation.getFinalScale());
setScaleY(mStateTransitionAnimation.getFinalScale());
}
}
- public void resetTransitionTransform(CellLayout layout) {
+ public void resetTransitionTransform() {
if (isSwitchingState()) {
setScaleX(mCurrentScale);
setScaleY(mCurrentScale);
@@ -3641,11 +3672,8 @@ public class Workspace extends PagedView
@Override
public void onAnimationStart(Animator animation) {
- if (mState == State.SPRING_LOADED) {
- // Show the page indicator at the same time as the rest of the transition.
- showPageIndicatorAtCurrentScroll();
- }
mTransitionProgress = 0;
+ onStartStateTransition();
}
@Override
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index e84d3b4e6..9d9e9fb1a 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -16,6 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -24,17 +27,14 @@ import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
+import android.util.Property;
import android.view.View;
-import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.DecelerateInterpolator;
+import com.android.launcher3.LauncherStateTransitionAnimation.AnimationConfig;
+import com.android.launcher3.Workspace.State;
import com.android.launcher3.anim.AnimationLayerSet;
-import com.android.launcher3.anim.PropertyListBuilder;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dragndrop.DragLayer;
-import com.android.launcher3.util.Thunk;
/**
* A convenience class to update a view's visibility state after an alpha animation.
@@ -131,78 +131,24 @@ class ZoomInInterpolator implements TimeInterpolator {
}
/**
- * Stores the transition states for convenience.
- */
-class TransitionStates {
-
- // Raw states
- final boolean oldStateIsNormal;
- final boolean oldStateIsSpringLoaded;
- final boolean oldStateIsNormalHidden;
- final boolean oldStateIsOverviewHidden;
- final boolean oldStateIsOverview;
-
- final boolean stateIsNormal;
- final boolean stateIsSpringLoaded;
- final boolean stateIsNormalHidden;
- final boolean stateIsOverviewHidden;
- final boolean stateIsOverview;
-
- // Convenience members
- final boolean workspaceToAllApps;
- final boolean overviewToAllApps;
- final boolean allAppsToWorkspace;
- final boolean workspaceToOverview;
- final boolean overviewToWorkspace;
-
- public TransitionStates(final Workspace.State fromState, final Workspace.State toState) {
- oldStateIsNormal = (fromState == Workspace.State.NORMAL);
- oldStateIsSpringLoaded = (fromState == Workspace.State.SPRING_LOADED);
- oldStateIsNormalHidden = (fromState == Workspace.State.NORMAL_HIDDEN);
- oldStateIsOverviewHidden = (fromState == Workspace.State.OVERVIEW_HIDDEN);
- oldStateIsOverview = (fromState == Workspace.State.OVERVIEW);
-
- stateIsNormal = (toState == Workspace.State.NORMAL);
- stateIsSpringLoaded = (toState == Workspace.State.SPRING_LOADED);
- stateIsNormalHidden = (toState == Workspace.State.NORMAL_HIDDEN);
- stateIsOverviewHidden = (toState == Workspace.State.OVERVIEW_HIDDEN);
- stateIsOverview = (toState == Workspace.State.OVERVIEW);
-
- workspaceToOverview = (oldStateIsNormal && stateIsOverview);
- workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
- overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
- overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
- allAppsToWorkspace = (oldStateIsNormalHidden && stateIsNormal);
- }
-}
-
-/**
* Manages the animations between each of the workspace states.
*/
public class WorkspaceStateTransitionAnimation {
- public static final String TAG = "WorkspaceStateTransitionAnimation";
-
- @Thunk static final int BACKGROUND_FADE_OUT_DURATION = 350;
+ private static final PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter();
- final @Thunk Launcher mLauncher;
- final @Thunk Workspace mWorkspace;
+ private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
- @Thunk AnimatorSet mStateAnimator;
+ public final int mWorkspaceScrimAlpha;
- @Thunk float mCurrentScale;
- @Thunk float mNewScale;
+ private final Launcher mLauncher;
+ private final Workspace mWorkspace;
- @Thunk final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
+ private final float mSpringLoadedShrinkFactor;
+ private final float mOverviewModeShrinkFactor;
+ private final boolean mWorkspaceFadeInAdjacentScreens;
- @Thunk float mSpringLoadedShrinkFactor;
- @Thunk float mOverviewModeShrinkFactor;
- @Thunk float mWorkspaceScrimAlpha;
- @Thunk int mAllAppsTransitionTime;
- @Thunk int mOverviewTransitionTime;
- @Thunk int mOverlayTransitionTime;
- @Thunk int mSpringLoadedTransitionTime;
- @Thunk boolean mWorkspaceFadeInAdjacentScreens;
+ private float mNewScale;
public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
mLauncher = launcher;
@@ -210,32 +156,24 @@ public class WorkspaceStateTransitionAnimation {
DeviceProfile grid = mLauncher.getDeviceProfile();
Resources res = launcher.getResources();
- mAllAppsTransitionTime = res.getInteger(R.integer.config_allAppsTransitionTime);
- mOverviewTransitionTime = res.getInteger(R.integer.config_overviewTransitionTime);
- mOverlayTransitionTime = res.getInteger(R.integer.config_overlayTransitionTime);
- mSpringLoadedTransitionTime = mOverlayTransitionTime / 2;
mSpringLoadedShrinkFactor = mLauncher.getDeviceProfile().workspaceSpringLoadShrinkFactor;
mOverviewModeShrinkFactor =
res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100f;
- mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha) / 100f;
+ mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha);
mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
}
- public void snapToPageFromOverView(int whichPage) {
- mWorkspace.snapToPage(whichPage, mOverviewTransitionTime, mZoomInInterpolator);
+ public void setState(Workspace.State toState) {
+ setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER);
}
- public AnimatorSet getAnimationToState(Workspace.State fromState, Workspace.State toState,
- boolean animated, AnimationLayerSet layerViews) {
- AccessibilityManager am = (AccessibilityManager)
- mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
- final boolean accessibilityEnabled = am.isEnabled();
- TransitionStates states = new TransitionStates(fromState, toState);
- int workspaceDuration = getAnimationDuration(states);
- animateWorkspace(states, animated, workspaceDuration, layerViews,
- accessibilityEnabled);
- animateBackgroundGradient(states, animated, BACKGROUND_FADE_OUT_DURATION);
- return mStateAnimator;
+ public void setStateWithAnimation(Workspace.State fromState, Workspace.State toState,
+ AnimatorSet anim, AnimationLayerSet layerViews, AnimationConfig config) {
+ long duration = config.getDuration(toState == State.NORMAL
+ ? fromState.transitionDuration : toState.transitionDuration);
+ AnimatedPropertySetter proertSetter =
+ new AnimatedPropertySetter(duration, layerViews, anim);
+ setWorkspaceProperty(toState, proertSetter);
}
public float getFinalScale() {
@@ -243,242 +181,138 @@ public class WorkspaceStateTransitionAnimation {
}
/**
- * Returns the proper animation duration for a transition.
- */
- private int getAnimationDuration(TransitionStates states) {
- if (states.workspaceToAllApps || states.overviewToAllApps) {
- return mAllAppsTransitionTime;
- } else if (states.workspaceToOverview || states.overviewToWorkspace) {
- return mOverviewTransitionTime;
- } else if (mLauncher.mState == Launcher.State.WORKSPACE_SPRING_LOADED
- || states.oldStateIsNormal && states.stateIsSpringLoaded) {
- return mSpringLoadedTransitionTime;
- } else {
- return mOverlayTransitionTime;
- }
- }
-
- /**
* Starts a transition animation for the workspace.
*/
- private void animateWorkspace(final TransitionStates states, final boolean animated,
- final int duration, AnimationLayerSet layerViews, final boolean accessibilityEnabled) {
- // Cancel existing workspace animations and create a new animator set if requested
- cancelAnimation();
- if (animated) {
- mStateAnimator = LauncherAnimUtils.createAnimatorSet();
- }
-
+ private void setWorkspaceProperty(Workspace.State state, PropertySetter propertySetter) {
// Update the workspace state
- float finalBackgroundAlpha = (states.stateIsSpringLoaded || states.stateIsOverview) ?
- 1.0f : 0f;
- float finalHotseatAlpha = (states.stateIsNormal || states.stateIsSpringLoaded ||
- states.stateIsNormalHidden) ? 1f : 0f;
-
- float finalWorkspaceTranslationY = 0;
- if (states.stateIsOverview || states.stateIsOverviewHidden) {
- finalWorkspaceTranslationY = mWorkspace.getOverviewModeTranslationY();
- } else if (states.stateIsSpringLoaded) {
- finalWorkspaceTranslationY = mWorkspace.getSpringLoadedTranslationY();
- }
-
- final int childCount = mWorkspace.getChildCount();
-
- mNewScale = 1.0f;
+ int finalBackgroundAlpha = state.hasScrim ? 255 : 0;
- if (states.oldStateIsOverview) {
- mWorkspace.disableFreeScroll();
- } else if (states.stateIsOverview) {
- mWorkspace.enableFreeScroll();
- }
-
- if (!states.stateIsNormal) {
- if (states.stateIsSpringLoaded) {
- mNewScale = mSpringLoadedShrinkFactor;
- } else if (states.stateIsOverview || states.stateIsOverviewHidden) {
+ final float finalWorkspaceTranslationY;
+ switch (state) {
+ case OVERVIEW:
mNewScale = mOverviewModeShrinkFactor;
- }
+ finalWorkspaceTranslationY = mWorkspace.getOverviewModeTranslationY();
+ break;
+ case SPRING_LOADED:
+ mNewScale = mSpringLoadedShrinkFactor;
+ finalWorkspaceTranslationY = mWorkspace.getSpringLoadedTranslationY();
+ break;
+ default:
+ mNewScale = 1f;
+ finalWorkspaceTranslationY = 0;
}
int toPage = mWorkspace.getPageNearestToCenterOfScreen();
- // TODO: Animate the celllayout alpha instead of the pages.
+ final int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
- float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
- float finalAlpha;
- if (states.stateIsOverviewHidden) {
- finalAlpha = 0f;
- } else if(states.stateIsNormalHidden) {
- finalAlpha = (i == mWorkspace.getNextPage()) ? 1 : 0;
- } else if (states.stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
- finalAlpha = (i == toPage) ? 1f : 0f;
- } else {
- finalAlpha = 1f;
+ propertySetter.setInt(cl.getScrimBackground(),
+ DRAWABLE_ALPHA, finalBackgroundAlpha, mZoomInInterpolator);
+
+ // Only animate the page alpha when we actually fade pages
+ if (mWorkspaceFadeInAdjacentScreens) {
+ float finalAlpha = state == State.NORMAL && i != toPage ? 0 : 1f;
+ propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
+ finalAlpha, mZoomInInterpolator);
}
+ }
- // If we are animating to/from the small state, then hide the side pages and fade the
- // current page in
- if (!FeatureFlags.NO_ALL_APPS_ICON && !mWorkspace.isSwitchingState()) {
- if (states.workspaceToAllApps || states.allAppsToWorkspace) {
- boolean isCurrentPage = (i == toPage);
- if (states.allAppsToWorkspace && isCurrentPage) {
- initialAlpha = 0f;
- } else if (!isCurrentPage) {
- initialAlpha = finalAlpha = 0f;
- }
- cl.setShortcutAndWidgetAlpha(initialAlpha);
- }
- }
+ float finalHotseatAlpha = state.hotseatAlpha;
- if (animated) {
- float oldBackgroundAlpha = cl.getBackgroundAlpha();
- if (initialAlpha != finalAlpha) {
- Animator alphaAnim = ObjectAnimator.ofFloat(
- cl.getShortcutsAndWidgets(), View.ALPHA, finalAlpha);
- alphaAnim.setDuration(duration)
- .setInterpolator(mZoomInInterpolator);
- mStateAnimator.play(alphaAnim);
- }
- if (oldBackgroundAlpha != 0 || finalBackgroundAlpha != 0) {
- ValueAnimator bgAnim = ObjectAnimator.ofFloat(cl, "backgroundAlpha",
- oldBackgroundAlpha, finalBackgroundAlpha);
- bgAnim.setInterpolator(mZoomInInterpolator);
- bgAnim.setDuration(duration);
- mStateAnimator.play(bgAnim);
- }
- } else {
- cl.setBackgroundAlpha(finalBackgroundAlpha);
- cl.setShortcutAndWidgetAlpha(finalAlpha);
+ // This is true when transitioning between:
+ // - Overview <-> Workspace
+ propertySetter.setViewAlpha(null, mLauncher.getOverviewPanel(), 1 - finalHotseatAlpha);
+ propertySetter.setViewAlpha(mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha),
+ mLauncher.getHotseat(), finalHotseatAlpha);
+
+ propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, mZoomInInterpolator);
+ propertySetter.setFloat(mWorkspace, View.TRANSLATION_Y,
+ finalWorkspaceTranslationY, mZoomInInterpolator);
+
+ // Set scrim
+ propertySetter.setInt(mLauncher.getDragLayer().getScrim(), DRAWABLE_ALPHA,
+ state.hasScrim ? mWorkspaceScrimAlpha : 0, new DecelerateInterpolator(1.5f));
+ }
+
+ private static class PropertySetter {
+
+ public void setViewAlpha(Animator anim, View view, float alpha) {
+ if (anim != null) {
+ anim.end();
+ return;
}
+ view.setAlpha(alpha);
+ AlphaUpdateListener.updateVisibility(view, isAccessibilityEnabled(view));
}
- final ViewGroup overviewPanel = mLauncher.getOverviewPanel();
-
- float finalOverviewPanelAlpha = states.stateIsOverview ? 1f : 0f;
- if (animated) {
- // This is true when transitioning between:
- // - Overview <-> Workspace
- // - Overview <-> Widget Tray
- if (finalOverviewPanelAlpha != overviewPanel.getAlpha()) {
- Animator overviewPanelAlpha = ObjectAnimator.ofFloat(
- overviewPanel, View.ALPHA, finalOverviewPanelAlpha);
- overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel,
- accessibilityEnabled));
- layerViews.addView(overviewPanel);
-
- if (states.overviewToWorkspace) {
- overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
- } else if (states.workspaceToOverview) {
- overviewPanelAlpha.setInterpolator(null);
- }
+ public <T> void setFloat(T target, Property<T, Float> property, float value,
+ TimeInterpolator interpolator) {
+ property.set(target, value);
+ }
- overviewPanelAlpha.setDuration(duration);
- mStateAnimator.play(overviewPanelAlpha);
- }
+ public <T> void setInt(T target, Property<T, Integer> property, int value,
+ TimeInterpolator interpolator) {
+ property.set(target, value);
+ }
- Animator scale = LauncherAnimUtils.ofPropertyValuesHolder(mWorkspace,
- new PropertyListBuilder().scale(mNewScale)
- .translationY(finalWorkspaceTranslationY).build())
- .setDuration(duration);
- scale.setInterpolator(mZoomInInterpolator);
- mStateAnimator.play(scale);
-
- // For animation optimization, we may need to provide the Launcher transition
- // with a set of views on which to force build and manage layers in certain scenarios.
- layerViews.addView(mLauncher.getHotseat());
- layerViews.addView(mWorkspace.getPageIndicator());
-
- Animator hotseatAlpha = mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha);
- if (states.workspaceToOverview) {
- hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
- } else if (states.overviewToWorkspace) {
- hotseatAlpha.setInterpolator(null);
- }
- hotseatAlpha.setDuration(duration);
- mStateAnimator.play(hotseatAlpha);
- mStateAnimator.addListener(new AnimatorListenerAdapter() {
- boolean canceled = false;
- @Override
- public void onAnimationCancel(Animator animation) {
- canceled = true;
- }
+ protected boolean isAccessibilityEnabled(View v) {
+ AccessibilityManager am = (AccessibilityManager)
+ v.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+ return am.isEnabled();
+ }
+ }
- @Override
- public void onAnimationStart(Animator animation) {
- mWorkspace.getPageIndicator().setShouldAutoHide(!states.stateIsSpringLoaded);
- }
+ private static class AnimatedPropertySetter extends PropertySetter {
+
+ private final long mDuration;
+ private final AnimationLayerSet mLayerViews;
+ private final AnimatorSet mStateAnimator;
+
+ AnimatedPropertySetter(long duration, AnimationLayerSet layerView, AnimatorSet anim) {
+ mDuration = duration;
+ mLayerViews = layerView;
+ mStateAnimator = anim;
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
- mStateAnimator = null;
- if (canceled) return;
- if (accessibilityEnabled && overviewPanel.getVisibility() == View.VISIBLE) {
- overviewPanel.getChildAt(0).performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
- }
+ @Override
+ public void setViewAlpha(Animator anim, View view, float alpha) {
+ if (anim == null) {
+ if (view.getAlpha() == alpha) {
+ return;
}
- });
- } else {
- overviewPanel.setAlpha(finalOverviewPanelAlpha);
- AlphaUpdateListener.updateVisibility(overviewPanel, accessibilityEnabled);
- mWorkspace.getPageIndicator().setShouldAutoHide(!states.stateIsSpringLoaded);
-
- mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha).end();
- mWorkspace.setScaleX(mNewScale);
- mWorkspace.setScaleY(mNewScale);
- mWorkspace.setTranslationY(finalWorkspaceTranslationY);
-
- if (accessibilityEnabled && overviewPanel.getVisibility() == View.VISIBLE) {
- overviewPanel.getChildAt(0).performAccessibilityAction(
- AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
+ anim.addListener(new AlphaUpdateListener(view, isAccessibilityEnabled(view)));
}
+
+ anim.setDuration(mDuration).setInterpolator(getFadeInterpolator(alpha));
+ mLayerViews.addView(view);
+ mStateAnimator.play(anim);
}
- }
- /**
- * Animates the background scrim. Add to the state animator to prevent jankiness.
- *
- * @param states the current and final workspace states
- * @param animated whether or not to set the background alpha immediately
- * @duration duration of the animation
- */
- private void animateBackgroundGradient(TransitionStates states,
- boolean animated, int duration) {
-
- final DragLayer dragLayer = mLauncher.getDragLayer();
- final float startAlpha = dragLayer.getBackgroundAlpha();
- float finalAlpha = states.stateIsNormal || states.stateIsNormalHidden ?
- 0 : mWorkspaceScrimAlpha;
-
- if (finalAlpha != startAlpha) {
- if (animated) {
- // These properties refer to the background protection gradient used for AllApps
- // and Widget tray.
- ValueAnimator bgFadeOutAnimation = ValueAnimator.ofFloat(startAlpha, finalAlpha);
- bgFadeOutAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- dragLayer.setBackgroundAlpha(
- ((Float)animation.getAnimatedValue()).floatValue());
- }
- });
- bgFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
- bgFadeOutAnimation.setDuration(duration);
- mStateAnimator.play(bgFadeOutAnimation);
- } else {
- dragLayer.setBackgroundAlpha(finalAlpha);
+ @Override
+ public <T> void setFloat(T target, Property<T, Float> property, float value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return;
}
+ Animator anim = ObjectAnimator.ofFloat(target, property, value);
+ anim.setDuration(mDuration).setInterpolator(interpolator);
+ mStateAnimator.play(anim);
}
- }
- /**
- * Cancels the current animation.
- */
- private void cancelAnimation() {
- if (mStateAnimator != null) {
- mStateAnimator.setDuration(0);
- mStateAnimator.cancel();
+ @Override
+ public <T> void setInt(T target, Property<T, Integer> property, int value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return;
+ }
+ Animator anim = ObjectAnimator.ofInt(target, property, value);
+ anim.setDuration(mDuration).setInterpolator(interpolator);
+ mStateAnimator.play(anim);
+ }
+
+ private TimeInterpolator getFadeInterpolator(float finalAlpha) {
+ return finalAlpha == 0 ? new DecelerateInterpolator(2) : null;
}
- mStateAnimator = null;
}
} \ 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 bb0822f95..5642b4c01 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -11,12 +11,14 @@ import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.LauncherStateTransitionAnimation.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
@@ -329,15 +331,15 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
mAnimationDuration = SwipeDetector.calculateDuration(velocity, disp / mShiftRange);
}
- public boolean animateToAllApps(AnimatorSet animationOut, long duration) {
- boolean shouldPost = true;
+ public void animateToAllApps(AnimatorSet animationOut, AnimationConfig outConfig) {
+ outConfig.shouldPost = true;
if (animationOut == null) {
- return shouldPost;
+ return;
}
Interpolator interpolator;
if (mDetector.isIdleState()) {
preparePull(true);
- mAnimationDuration = duration;
+ mAnimationDuration = LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
mShiftStart = mAppsView.getTranslationY();
interpolator = mFastOutSlowInInterpolator;
} else {
@@ -347,9 +349,10 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
if (nextFrameProgress >= 0f) {
mProgress = nextFrameProgress;
}
- shouldPost = false;
+ outConfig.shouldPost = false;
}
+ outConfig.overrideDuration(mAnimationDuration);
ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
mProgress, 0f);
driftAndAlpha.setDuration(mAnimationDuration);
@@ -396,7 +399,6 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
}
});
mCurrentAnimation = animationOut;
- return shouldPost;
}
public void showDiscoveryBounce() {
@@ -432,15 +434,15 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
});
}
- public boolean animateToWorkspace(AnimatorSet animationOut, long duration) {
- boolean shouldPost = true;
+ public void animateToWorkspace(AnimatorSet animationOut, AnimationConfig outconfig) {
+ outconfig.shouldPost = true;
if (animationOut == null) {
- return shouldPost;
+ return;
}
Interpolator interpolator;
if (mDetector.isIdleState()) {
preparePull(true);
- mAnimationDuration = duration;
+ mAnimationDuration = LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
mShiftStart = mAppsView.getTranslationY();
interpolator = mFastOutSlowInInterpolator;
} else {
@@ -450,9 +452,10 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
if (nextFrameProgress <= 1f) {
mProgress = nextFrameProgress;
}
- shouldPost = false;
+ outconfig.shouldPost = false;
}
+ outconfig.overrideDuration(mAnimationDuration);
ObjectAnimator driftAndAlpha = ObjectAnimator.ofFloat(this, "progress",
mProgress, 1f);
driftAndAlpha.setDuration(mAnimationDuration);
@@ -479,7 +482,6 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
}
});
mCurrentAnimation = animationOut;
- return shouldPost;
}
public void finishPullUp() {
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 31255b7f0..8386f8ffa 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -16,6 +16,8 @@
package com.android.launcher3.dragndrop;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_SHORT_TIMEOUT;
+
import android.content.ComponentName;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -261,8 +263,7 @@ public class DragController implements DragDriver.EventListener, TouchController
if (!accepted) {
// If it was not accepted, cleanup the state. If it was accepted, it is the
// responsibility of the drop target to cleanup the state.
- mLauncher.exitSpringLoadedDragMode(false,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
mDragObject.deferDragViewCleanupPostAnimation = false;
}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 95223c3f7..bc5aafc0a 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -25,8 +25,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.Region;
-import android.support.v4.graphics.ColorUtils;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -50,7 +49,6 @@ import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dynamicui.WallpaperColorInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
@@ -83,19 +81,15 @@ public class DragLayer extends InsettableFrameLayout {
private boolean mHoverPointClosesFolder = false;
private final Rect mHitRect = new Rect();
- private final Rect mHighlightRect = new Rect();
private TouchCompleteListener mTouchCompleteListener;
private int mTopViewIndex;
private int mChildCountOnLastUpdate = -1;
- // Darkening scrim
- private float mBackgroundAlpha = 0;
-
// Related to adjacent page hints
private final ViewGroupFocusHelper mFocusIndicatorHelper;
- private final WallpaperColorInfo mWallpaperColorInfo;
+ private final PageCutOutScrimDrawable mPageCutOutScrim;
// Related to pinch-to-go-to-overview gesture.
private PinchToOverviewListener mPinchListener = null;
@@ -118,7 +112,8 @@ public class DragLayer extends InsettableFrameLayout {
setChildrenDrawingOrderEnabled(true);
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
- mWallpaperColorInfo = WallpaperColorInfo.getInstance(getContext());
+ mPageCutOutScrim = new PageCutOutScrimDrawable(this);
+ mPageCutOutScrim.setCallback(this);
}
public void setup(Launcher launcher, DragController dragController,
@@ -141,6 +136,11 @@ public class DragLayer extends InsettableFrameLayout {
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || who == mPageCutOutScrim;
+ }
+
public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
? null : new PinchToOverviewListener(mLauncher);
@@ -772,48 +772,23 @@ public class DragLayer extends InsettableFrameLayout {
}
public void invalidateScrim() {
- if (mBackgroundAlpha > 0.0f) {
+ if (mPageCutOutScrim.getAlpha() > 0) {
invalidate();
}
}
+ public Drawable getScrim() {
+ return mPageCutOutScrim;
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
// Draw the background below children.
- if (mBackgroundAlpha > 0.0f) {
- // Update the scroll position first to ensure scrim cutout is in the right place.
- mLauncher.getWorkspace().computeScrollWithoutInvalidation();
-
- int alpha = (int) (mBackgroundAlpha * 255);
- CellLayout currCellLayout = mLauncher.getWorkspace().getCurrentDragOverlappingLayout();
- canvas.save();
- if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
- // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
- getDescendantRectRelativeToSelf(currCellLayout, mHighlightRect);
- canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
- }
- // for super light wallpaper it needs to be darken for contrast to workspace
- // for dark wallpapers the text is white so darkening works as well
- int color = ColorUtils.compositeColors(0x66000000, mWallpaperColorInfo.getMainColor());
- canvas.drawColor(ColorUtils.setAlphaComponent(color, alpha));
- canvas.restore();
- }
-
+ mPageCutOutScrim.draw(canvas);
mFocusIndicatorHelper.draw(canvas);
super.dispatchDraw(canvas);
}
- public void setBackgroundAlpha(float alpha) {
- if (alpha != mBackgroundAlpha) {
- mBackgroundAlpha = alpha;
- invalidate();
- }
- }
-
- public float getBackgroundAlpha() {
- return mBackgroundAlpha;
- }
-
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
diff --git a/src/com/android/launcher3/dragndrop/PageCutOutScrimDrawable.java b/src/com/android/launcher3/dragndrop/PageCutOutScrimDrawable.java
new file mode 100644
index 000000000..367124b5d
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/PageCutOutScrimDrawable.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 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.dragndrop;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.drawable.Drawable;
+import android.support.v4.graphics.ColorUtils;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.dynamicui.WallpaperColorInfo;
+
+/**
+ * Scrim drawable which draws a hole for the current drop target page.
+ */
+public class PageCutOutScrimDrawable extends Drawable {
+
+ private final Rect mHighlightRect = new Rect();
+ private final DragLayer mDragLayer;
+ private final Launcher mLauncher;
+ private final WallpaperColorInfo mWallpaperColorInfo;
+
+ private int mAlpha = 0;
+
+ public PageCutOutScrimDrawable(DragLayer dragLayer) {
+ mDragLayer = dragLayer;
+ mLauncher = Launcher.getLauncher(mDragLayer.getContext());
+ mWallpaperColorInfo = WallpaperColorInfo.getInstance(mLauncher);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ // Draw the background below children.
+ if (mAlpha > 0) {
+ // Update the scroll position first to ensure scrim cutout is in the right place.
+ mLauncher.getWorkspace().computeScrollWithoutInvalidation();
+ CellLayout currCellLayout = mLauncher.getWorkspace().getCurrentDragOverlappingLayout();
+ canvas.save();
+ if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
+ // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
+ mDragLayer.getDescendantRectRelativeToSelf(currCellLayout, mHighlightRect);
+ canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
+ }
+ // for super light wallpaper it needs to be darken for contrast to workspace
+ // for dark wallpapers the text is white so darkening works as well
+ int color = ColorUtils.compositeColors(0x66000000, mWallpaperColorInfo.getMainColor());
+ canvas.drawColor(ColorUtils.setAlphaComponent(color, mAlpha));
+ canvas.restore();
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (mAlpha != alpha) {
+ mAlpha = alpha;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public int getAlpha() {
+ return mAlpha;
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+}
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index a70a9bb1f..1da78349d 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -29,7 +29,7 @@ import android.os.Process;
import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.IconCache;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
@@ -83,8 +83,8 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
public com.android.launcher3.ShortcutInfo createShortcutInfo() {
// Total duration for the drop animation to complete.
long duration = mContext.getResources().getInteger(R.integer.config_dropAnimMaxDuration) +
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT +
- mContext.getResources().getInteger(R.integer.config_overlayTransitionTime) / 2;
+ LauncherAnimUtils.SPRING_LOADED_EXIT_SHORT_TIMEOUT +
+ LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
// Delay the actual accept() call until the drop animation is complete.
return LauncherAppsCompatVO.createShortcutInfoFromPinItemRequest(
mContext, mRequest, duration);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 4a60d4c56..fae420eef 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -16,6 +16,8 @@
package com.android.launcher3.folder;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_SHORT_TIMEOUT;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -1241,8 +1243,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher.getModelWriter());
}
- mLauncher.exitSpringLoadedDragMode(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_SHORT_TIMEOUT);
if (d.stateAnnouncer != null) {
d.stateAnnouncer.completeAction(R.string.item_moved);
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index cdb0ce367..ec448e997 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -16,6 +16,9 @@
package com.android.launcher3.folder;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -45,8 +48,6 @@ import com.android.launcher3.util.Themes;
import java.util.List;
-import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
-
/**
* Manages the opening and closing animations for a {@link Folder}.
*
@@ -77,19 +78,6 @@ public class FolderAnimationManager {
private final PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
- private static final Property<View, Float> SCALE_PROPERTY =
- new Property<View, Float>(Float.class, "scale") {
- @Override
- public Float get(View view) {
- return view.getScaleX();
- }
-
- @Override
- public void set(View view, Float scale) {
- view.setScaleX(scale);
- view.setScaleY(scale);
- }
- };
public FolderAnimationManager(Folder folder, boolean isOpening) {
mFolder = folder;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index d469eb254..900781cbb 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -296,7 +296,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
to = new Rect();
Workspace workspace = mLauncher.getWorkspace();
// Set cellLayout and this to it's final state to compute final animation locations
- workspace.setFinalTransitionTransform((CellLayout) getParent().getParent());
+ workspace.setFinalTransitionTransform();
float scaleX = getScaleX();
float scaleY = getScaleY();
setScaleX(1.0f);
@@ -305,7 +305,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
// Finished computing final animation locations, restore current state
setScaleX(scaleX);
setScaleY(scaleY);
- workspace.resetTransitionTransform((CellLayout) getParent().getParent());
+ workspace.resetTransitionTransform();
}
int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index d5c6515c0..1a6dade31 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -177,13 +177,11 @@ public class UserEventDispatcher {
}
public void logActionCommand(int command, int containerType) {
- logActionCommand(command, containerType, 0);
+ logActionCommand(command, newContainerTarget(containerType));
}
- public void logActionCommand(int command, int containerType, int pageIndex) {
- LauncherEvent event = newLauncherEvent(
- newCommandAction(command), newContainerTarget(containerType));
- event.srcTarget[0].pageIndex = pageIndex;
+ public void logActionCommand(int command, Target target) {
+ LauncherEvent event = newLauncherEvent(newCommandAction(command), target);
dispatchUserEvent(event, null);
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 78ecbc621..53a986258 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -336,17 +336,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
});
}
- // Notify launcher of widget update. From marshmallow onwards we use AppWidgetHost to
- // get widget update signals.
- if (!Utilities.ATLEAST_MARSHMALLOW &&
- (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) {
- scheduleCallbackTask(new CallbackTask() {
- @Override
- public void execute(Callbacks callbacks) {
- callbacks.notifyWidgetProvidersChanged();
- }
- });
- } else if (Utilities.ATLEAST_OREO && mOp == OP_ADD) {
+ if (Utilities.ATLEAST_OREO && mOp == OP_ADD) {
// Load widgets for the new package. Changes due to app updates are handled through
// AppWidgetHost events, this is just to initialize the long-press options.
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
index 15f5af625..ec6276478 100644
--- a/src/com/android/launcher3/util/FlingAnimation.java
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -1,5 +1,7 @@
package com.android.launcher3.util;
+import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -95,7 +97,7 @@ public class FlingAnimation implements AnimatorUpdateListener, Runnable {
Runnable onAnimationEndRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.exitSpringLoadedDragMode(false, 0);
+ mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
mDropTarget.completeDrop(mDragObject);
}
};
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index b6b3089b0..61a733338 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget;
+import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -32,7 +34,6 @@ import android.view.animation.DecelerateInterpolator;
import android.widget.Toast;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.DeleteDropTarget;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.ItemInfo;
@@ -41,7 +42,6 @@ import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.folder.Folder;
import com.android.launcher3.graphics.GradientView;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -264,11 +264,16 @@ abstract class BaseWidgetSheet extends AbstractFloatingView
@Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
targetParent.containerType = ContainerType.WIDGETS;
+ targetParent.cardinality = getElementsRowCount();
}
@Override
public final void logActionCommand(int command) {
- // TODO: be more specific
- mLauncher.getUserEventDispatcher().logActionCommand(command, ContainerType.WIDGETS);
+ Target target = newContainerTarget(ContainerType.WIDGETS);
+ target.cardinality = getElementsRowCount();
+ mLauncher.getUserEventDispatcher().logActionCommand(command, target);
}
+
+ protected abstract int getElementsRowCount();
+
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 201bd1c9c..3bb3fcb98 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -181,4 +181,9 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
setPadding(getPaddingLeft() + leftInset, getPaddingTop(),
getPaddingRight() + rightInset, getPaddingBottom() + bottomInset);
}
+
+ @Override
+ protected int getElementsRowCount() {
+ return 1;
+ }
}
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index 72277a253..a40ea1b64 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -219,4 +219,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet
sheet.open(animate);
return sheet;
}
+
+ @Override
+ protected int getElementsRowCount() {
+ return mAdapter.getItemCount();
+ }
}