Merge "Caching the uninstall disabled state for each userHandle" into ub-launcher3-master
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 5c8b080..6f40408 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -16,7 +16,7 @@
package com.android.launcher3;
-import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+import static com.android.launcher3.LauncherState.NORMAL;
import android.animation.AnimatorSet;
import android.animation.FloatArrayEvaluator;
@@ -235,7 +235,7 @@
public void run() {
completeDrop(d);
mDropTargetBar.onDragEnd();
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
+ mLauncher.getStateManager().goToState(NORMAL);
}
};
dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 775dad2..cd9fffc 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -19,8 +19,10 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
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;
@@ -58,7 +60,6 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
@@ -203,7 +204,7 @@
// Type: SparseArray<Parcelable>
private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel";
- private LauncherStateTransitionAnimation mStateTransitionAnimation;
+ private LauncherStateManager mStateManager;
private boolean mIsSafeModeEnabled;
@@ -257,7 +258,6 @@
private ModelWriter mModelWriter;
private IconCache mIconCache;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
- private final Handler mHandler = new Handler();
private boolean mHasFocus = false;
private ObjectAnimator mScrimAnimator;
@@ -271,11 +271,6 @@
// it from the context.
private SharedPreferences mSharedPrefs;
- // Exiting spring loaded mode happens with a delay. This runnable object triggers the
- // state transition. If another state transition happened during this delay,
- // simply unregister this runnable.
- private Runnable mExitSpringLoadedModeRunnable;
-
// Activity result which needs to be processed after workspace has loaded.
private ActivityResultInfo mPendingActivityResult;
/**
@@ -342,7 +337,7 @@
mDragController = new DragController(this);
mAllAppsController = new AllAppsTransitionController(this);
- mStateTransitionAnimation = new LauncherStateTransitionAnimation(this, mAllAppsController);
+ mStateManager = new LauncherStateManager(this, mAllAppsController);
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
@@ -430,8 +425,8 @@
recreate();
}
- public LauncherStateTransitionAnimation getStateTransition() {
- return mStateTransitionAnimation;
+ public LauncherStateManager getStateManager() {
+ return mStateManager;
}
protected void overrideTheme(boolean isDark, boolean supportsDarkText) {
@@ -565,7 +560,7 @@
Runnable exitSpringLoaded = new Runnable() {
@Override
public void run() {
- exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
};
@@ -585,11 +580,11 @@
}
return;
} else if (requestCode == REQUEST_PICK_WALLPAPER) {
- if (resultCode == RESULT_OK && isInState(LauncherState.OVERVIEW)) {
+ if (resultCode == RESULT_OK && isInState(OVERVIEW)) {
// User could have free-scrolled between pages before picking a wallpaper; make sure
// we move to the closest one now.
mWorkspace.setCurrentPage(mWorkspace.getPageNearestToCenterOfScreen());
- showWorkspace(false);
+ mStateManager.goToState(NORMAL, false);
}
return;
}
@@ -617,7 +612,7 @@
final Runnable onComplete = new Runnable() {
@Override
public void run() {
- exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
+ getStateManager().goToState(NORMAL);
}
};
@@ -745,7 +740,7 @@
@Override
public void run() {
completeAddAppWidget(appWidgetId, requestArgs, layout, null);
- exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
};
} else if (resultCode == RESULT_CANCELED) {
@@ -990,9 +985,16 @@
AbstractFloatingView.closeAllOpenViews(this);
// Show the overview mode if we are on the workspace
- if (isInState(LauncherState.NORMAL) && !mWorkspace.isSwitchingState()) {
- mOverviewPanel.requestFocus();
- showOverviewMode(true, true /* requestButtonFocus */);
+ if (isInState(NORMAL) && !mWorkspace.isSwitchingState()) {
+ mStateManager.goToState(OVERVIEW, true /* animate */, new Runnable() {
+ @Override
+ public void run() {
+ // Hitting the menu button when in touch mode does not trigger touch
+ // mode to be disabled, so if requested, force focus on one of the
+ // overview panel buttons.
+ mOverviewPanel.requestFocusFromTouch();
+ }
+ });
}
}
return true;
@@ -1025,15 +1027,11 @@
return;
}
- int stateOrdinal = savedState.getInt(RUNTIME_STATE, LauncherState.NORMAL.ordinal);
+ int stateOrdinal = savedState.getInt(RUNTIME_STATE, NORMAL.ordinal);
LauncherState[] stateValues = LauncherState.values();
LauncherState state = stateValues[stateOrdinal];
if (!state.doNotRestore) {
- if (state == LauncherState.ALL_APPS) {
- showAppsView(false /* animated */);
- } else {
- // TODO: Add logic for other states
- }
+ mStateManager.goToState(state, false /* animated */);
}
PendingRequestArgs requestArgs = savedState.getParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS);
@@ -1311,10 +1309,7 @@
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
if (mAppsView != null && mPendingRequestArgs == null) {
- if (!showWorkspace(false)) {
- // If we are already on the workspace, then manually reset all apps
- mAppsView.reset();
- }
+ mStateManager.goToState(NORMAL);
}
mShouldFadeInScrim = true;
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
@@ -1414,7 +1409,7 @@
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
// Check this condition before handling isActionMain, as this will get reset.
- boolean shouldMoveToDefaultScreen = alreadyOnHome && isInState(LauncherState.NORMAL)
+ boolean shouldMoveToDefaultScreen = alreadyOnHome && isInState(NORMAL)
&& AbstractFloatingView.getTopOpenView(this) == null;
boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
@@ -1438,7 +1433,7 @@
// In all these cases, only animate if we're already on home
AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
- showWorkspace(alreadyOnHome /* animated */);
+ mStateManager.goToState(NORMAL, alreadyOnHome /* animated */);
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
@@ -1615,7 +1610,7 @@
}
// We need to show the workspace after starting the search
- showWorkspace(true);
+ mStateManager.goToState(NORMAL);
}
/**
@@ -1707,7 +1702,7 @@
@Override
public void run() {
// Exit spring loaded mode if necessary after adding the widget
- exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
}
};
completeAddAppWidget(appWidgetId, info, boundWidget, addFlowHandler.getProviderInfo(this));
@@ -1888,9 +1883,9 @@
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
if (topView != null) {
topView.onBackPressed();
- } else if (!isInState(LauncherState.NORMAL)) {
+ } else if (!isInState(NORMAL)) {
ued.logActionCommand(Action.Command.BACK, mWorkspace.getState().containerType);
- showWorkspace(true);
+ mStateManager.goToState(NORMAL);
} else {
// Back button is a no-op here, but give at least some feedback for the button press
mWorkspace.showOutlinesTemporarily();
@@ -1914,23 +1909,23 @@
}
if (v instanceof Workspace) {
- if (isInState(LauncherState.OVERVIEW)) {
+ if (isInState(OVERVIEW)) {
getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH,
LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, mWorkspace.getCurrentPage());
- showWorkspace(true);
+ mStateManager.goToState(NORMAL);
}
return;
}
if (v instanceof CellLayout) {
- if (isInState(LauncherState.OVERVIEW)) {
+ if (isInState(OVERVIEW)) {
int page = mWorkspace.indexOfChild(v);
getUserEventDispatcher().logActionOnContainer(LauncherLogProto.Action.Type.TOUCH,
LauncherLogProto.Action.Direction.NONE,
LauncherLogProto.ContainerType.OVERVIEW, page);
mWorkspace.snapToPageFromOverView(page);
- showWorkspace(true);
+ mStateManager.goToState(NORMAL);
}
return;
}
@@ -2002,12 +1997,12 @@
*/
protected void onClickAllAppsButton(View v) {
if (LOGD) Log.d(TAG, "onClickAllAppsButton");
- if (!isInState(LauncherState.ALL_APPS)) {
+ if (!isInState(ALL_APPS)) {
getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.ALL_APPS_BUTTON);
- showAppsView(true /* animated */);
+ mStateManager.goToState(ALL_APPS);
} else {
- showWorkspace(true);
+ mStateManager.goToState(NORMAL);
}
}
@@ -2333,18 +2328,18 @@
public boolean onLongClick(View v) {
if (!isDraggingEnabled()) return false;
if (isWorkspaceLocked()) return false;
- if (!isInState(LauncherState.NORMAL) && !isInState(LauncherState.OVERVIEW)) return false;
+ if (!isInState(NORMAL) && !isInState(OVERVIEW)) return false;
boolean ignoreLongPressToOverview =
mDeviceProfile.shouldIgnoreLongPressToOverview(mLastDispatchTouchEventX);
if (v instanceof Workspace) {
- if (!isInState(LauncherState.OVERVIEW)) {
+ if (!isInState(OVERVIEW)) {
if (!mWorkspace.isTouchActive() && !ignoreLongPressToOverview) {
getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
Action.Direction.NONE, ContainerType.WORKSPACE,
mWorkspace.getCurrentPage());
- showOverviewMode(true);
+ getStateManager().goToState(OVERVIEW);
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
return true;
@@ -2381,7 +2376,7 @@
getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
Action.Direction.NONE, ContainerType.WORKSPACE,
mWorkspace.getCurrentPage());
- showOverviewMode(true);
+ getStateManager().goToState(OVERVIEW);
}
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
@@ -2436,134 +2431,16 @@
}
}
- public boolean showWorkspace(boolean animated) {
- return showWorkspace(animated, null);
- }
-
- public boolean showWorkspace(boolean animated, Runnable onCompleteRunnable) {
- boolean changed = !isInState(LauncherState.NORMAL);
- if (changed || mAllAppsController.isTransitioning()) {
- mWorkspace.setVisibility(View.VISIBLE);
- mStateTransitionAnimation.goToState(LauncherState.NORMAL, animated, onCompleteRunnable);
-
- // Set focus to the AppsCustomize button
- if (mAllAppsButton != null) {
- mAllAppsButton.requestFocus();
- }
- }
-
- if (changed) {
- // Send an accessibility event to announce the context change
- getWindow().getDecorView()
- .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- }
- return changed;
- }
-
- /**
- * Shows the overview button.
- */
- public void showOverviewMode(boolean animated) {
- showOverviewMode(animated, false);
- }
-
- /**
- * Shows the overview button, and if {@param requestButtonFocus} is set, will force the focus
- * onto one of the overview panel buttons.
- */
- void showOverviewMode(boolean animated, boolean requestButtonFocus) {
- Runnable postAnimRunnable = null;
- if (requestButtonFocus) {
- postAnimRunnable = new Runnable() {
- @Override
- public void run() {
- // Hitting the menu button when in touch mode does not trigger touch mode to
- // be disabled, so if requested, force focus on one of the overview panel
- // buttons.
- mOverviewPanel.requestFocusFromTouch();
- }
- };
- }
- mWorkspace.setVisibility(View.VISIBLE);
- mStateTransitionAnimation.goToState(LauncherState.OVERVIEW, animated, postAnimRunnable);
-
- // If animated from long press, then don't allow any of the controller in the drag
- // layer to intercept any remaining touch.
- mWorkspace.requestDisallowInterceptTouchEvent(animated);
- }
-
- /**
- * Shows the apps 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.
- public boolean showAppsView(boolean animated) {
- if (!(isInState(LauncherState.NORMAL) ||
- (isInState(LauncherState.ALL_APPS) && mAllAppsController.isTransitioning()))) {
- return false;
- }
-
- // This is a safe and supported transition to bypass spring_loaded mode.
- if (mExitSpringLoadedModeRunnable != null) {
- mHandler.removeCallbacks(mExitSpringLoadedModeRunnable);
- mExitSpringLoadedModeRunnable = null;
- }
-
- mStateTransitionAnimation.goToState(LauncherState.ALL_APPS, animated, null);
-
- // Change the state *after* we've called all the transition code
- AbstractFloatingView.closeAllOpenViews(this);
-
- // Send an accessibility event to announce the context change
- getWindow().getDecorView()
- .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- return true;
- }
-
- public void enterSpringLoadedDragMode() {
- if (LOGD) Log.d(TAG, String.format("enterSpringLoadedDragMode [mState=%s",
- mWorkspace.getState().ordinal));
- if (isInState(LauncherState.SPRING_LOADED)) {
- return;
- }
- mStateTransitionAnimation.goToState(LauncherState.SPRING_LOADED, true, null);
- }
-
- public void exitSpringLoadedDragMode(int delay) {
- exitSpringLoadedDragMode(delay, null);
- }
-
- public void exitSpringLoadedDragMode(int delay, final Runnable onCompleteRunnable) {
- if (!isInState(LauncherState.SPRING_LOADED)) return;
-
- if (mExitSpringLoadedModeRunnable != null) {
- mHandler.removeCallbacks(mExitSpringLoadedModeRunnable);
- }
- mExitSpringLoadedModeRunnable = new Runnable() {
- @Override
- public void run() {
- showWorkspace(true, onCompleteRunnable);
- mExitSpringLoadedModeRunnable = null;
- }
- };
- mHandler.postDelayed(mExitSpringLoadedModeRunnable, delay);
- }
-
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
final boolean result = super.dispatchPopulateAccessibilityEvent(event);
final List<CharSequence> text = event.getText();
text.clear();
// Populate event with a fake title based on the current state.
- if (isInState(LauncherState.ALL_APPS)) {
- text.add(getString(R.string.all_apps_button_label));
- } else if (mWorkspace != null) {
- text.add(mWorkspace.getCurrentPageDescription());
- } else {
- text.add(getString(R.string.all_apps_home_button_label));
- }
+ // TODO: When can workspace be null?
+ text.add(mWorkspace == null
+ ? getString(R.string.all_apps_home_button_label)
+ : mWorkspace.getState().getDescription(this));
return result;
}
@@ -3114,7 +2991,7 @@
if (mAppsView != null) {
Executor pendingExecutor = getPendingExecutor();
- if (pendingExecutor != null && !isInState(LauncherState.ALL_APPS)) {
+ if (pendingExecutor != null && !isInState(ALL_APPS)) {
// Wait until the fade in animation has finished before setting all apps list.
pendingExecutor.execute(r);
return;
@@ -3304,7 +3181,7 @@
}
private boolean shouldShowDiscoveryBounce() {
- return isInState(LauncherState.NORMAL)
+ return isInState(NORMAL)
&& !mSharedPrefs.getBoolean(AllAppsState.APPS_VIEW_SHOWN, false)
&& !UserManagerCompat.getInstance(this).isDemoUser();
}
@@ -3364,7 +3241,7 @@
List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
ArrayList<KeyboardShortcutInfo> shortcutInfos = new ArrayList<>();
- if (isInState(LauncherState.NORMAL)) {
+ if (isInState(NORMAL)) {
shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.all_apps_button_label),
KeyEvent.KEYCODE_A, KeyEvent.META_CTRL_ON));
}
@@ -3390,8 +3267,8 @@
if (event.hasModifiers(KeyEvent.META_CTRL_ON)) {
switch (keyCode) {
case KeyEvent.KEYCODE_A:
- if (isInState(LauncherState.NORMAL)) {
- showAppsView(true);
+ if (isInState(NORMAL)) {
+ getStateManager().goToState(ALL_APPS);
return true;
}
break;
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 3585110..dfe51af 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -38,7 +38,6 @@
public static final int OVERVIEW_TRANSITION_MS = 250;
public static final int SPRING_LOADED_TRANSITION_MS = 150;
public static final int SPRING_LOADED_EXIT_DELAY = 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() {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 9d01ed8..de3f441 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -17,8 +17,7 @@
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
-
-import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
import android.view.View;
@@ -121,11 +120,21 @@
return new float[] {1, 0};
}
- public void onStateEnabled(Launcher launcher) { }
+ public void onStateEnabled(Launcher launcher) {
+ dispatchWindowStateChanged(launcher);
+ }
public void onStateDisabled(Launcher launcher) { }
public View getFinalFocus(Launcher launcher) {
return launcher.getWorkspace();
}
+
+ public String getDescription(Launcher launcher) {
+ return launcher.getWorkspace().getCurrentPageDescription();
+ }
+
+ protected static void dispatchWindowStateChanged(Launcher launcher) {
+ launcher.getWindow().getDecorView().sendAccessibilityEvent(TYPE_WINDOW_STATE_CHANGED);
+ }
}
diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateManager.java
similarity index 77%
rename from src/com/android/launcher3/LauncherStateTransitionAnimation.java
rename to src/com/android/launcher3/LauncherStateManager.java
index eec8b31..4298174 100644
--- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -68,23 +68,73 @@
* - From the center workspace
* - From another workspace
*/
-public class LauncherStateTransitionAnimation {
+public class LauncherStateManager {
- public static final String TAG = "LSTAnimation";
+ public static final String TAG = "StateManager";
private final AnimationConfig mConfig = new AnimationConfig();
private final Handler mUiHandler;
private final Launcher mLauncher;
private final AllAppsTransitionController mAllAppsController;
- public LauncherStateTransitionAnimation(
+ public LauncherStateManager(
Launcher l, AllAppsTransitionController allAppsController) {
mUiHandler = new Handler(Looper.getMainLooper());
mLauncher = l;
mAllAppsController = allAppsController;
}
+ /**
+ * @see #goToState(LauncherState, boolean, Runnable)
+ */
+ public void goToState(LauncherState state) {
+ goToState(state, true, 0, null);
+ }
+
+ /**
+ * @see #goToState(LauncherState, boolean, Runnable)
+ */
+ public void goToState(LauncherState state, boolean animated) {
+ goToState(state, animated, 0, null);
+ }
+
+ /**
+ * Changes the Launcher state to the provided state.
+ *
+ * @param animated false if the state should change immediately without any animation,
+ * true otherwise
+ * @paras onCompleteRunnable any action to perform at the end of the transition, of null.
+ */
public void goToState(LauncherState state, boolean animated, Runnable onCompleteRunnable) {
+ goToState(state, animated, 0, onCompleteRunnable);
+ }
+
+ /**
+ * Changes the Launcher state to the provided state after the given delay.
+ */
+ public void goToState(LauncherState state, long delay, Runnable onCompleteRunnable) {
+ goToState(state, true, delay, onCompleteRunnable);
+ }
+
+ /**
+ * Changes the Launcher state to the provided state after the given delay.
+ */
+ public void goToState(LauncherState state, long delay) {
+ goToState(state, true, delay, null);
+ }
+
+ private void goToState(LauncherState state, boolean animated, long delay,
+ Runnable onCompleteRunnable) {
+ if (mLauncher.isInState(state) && mConfig.mCurrentAnimation == null
+ && !mAllAppsController.isTransitioning()) {
+
+ // Run any queued runnable
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+ return;
+ }
+
// Cancel the current animation
mConfig.reset();
@@ -102,7 +152,9 @@
AnimatorSet animation = createAnimationToNewWorkspace(state, onCompleteRunnable);
Runnable runnable = new StartAnimRunnable(animation, state.getFinalFocus(mLauncher));
- if (mConfig.shouldPost) {
+ if (delay > 0) {
+ mUiHandler.postDelayed(runnable, delay);
+ } else if (mConfig.shouldPost) {
mUiHandler.post(runnable);
} else {
runnable.run();
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 5258fba..f55455b 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -49,7 +49,6 @@
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.touch.OverScroll;
-import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -87,8 +86,6 @@
public static final int INVALID_RESTORE_PAGE = -1001;
private boolean mFreeScroll = false;
- private int mFreeScrollMinScrollX = -1;
- private int mFreeScrollMaxScrollX = -1;
protected int mFlingThresholdVelocity;
protected int mMinFlingVelocity;
@@ -137,7 +134,6 @@
protected int mTouchSlop;
private int mMaximumVelocity;
protected boolean mAllowOverScroll = true;
- protected int[] mTempVisiblePagesRange = new int[2];
protected static final int INVALID_POINTER = -1;
@@ -380,16 +376,8 @@
}
private int validateNewPage(int newPage) {
- int validatedPage = newPage;
- // When in free scroll mode, we need to clamp to the free scroll page range.
- if (mFreeScroll) {
- getFreeScrollPageRange(mTempVisiblePagesRange);
- validatedPage = Math.max(mTempVisiblePagesRange[0],
- Math.min(newPage, mTempVisiblePagesRange[1]));
- }
// Ensure that it is clamped by the actual set of children in all cases
- validatedPage = Utilities.boundToRange(validatedPage, 0, getPageCount() - 1);
- return validatedPage;
+ return Utilities.boundToRange(newPage, 0, getPageCount() - 1);
}
/**
@@ -491,13 +479,11 @@
if (mFreeScroll) {
// If the scroller is trying to move to a location beyond the maximum allowed
// in the free scroll mode, we make sure to end the scroll operation.
- if (!mScroller.isFinished() &&
- (x > mFreeScrollMaxScrollX || x < mFreeScrollMinScrollX)) {
+ if (!mScroller.isFinished() && (x > mMaxScrollX || x < 0)) {
forceFinishScroller(false);
}
- x = Math.min(x, mFreeScrollMaxScrollX);
- x = Math.max(x, mFreeScrollMinScrollX);
+ x = Utilities.boundToRange(x, 0, mMaxScrollX);
}
mUnboundedScrollX = x;
@@ -886,7 +872,7 @@
return 0;
}
- @Thunk void updateMaxScrollX() {
+ private void updateMaxScrollX() {
mMaxScrollX = computeMaxScrollX();
}
@@ -915,13 +901,11 @@
// This ensures that when children are added, they get the correct transforms / alphas
// in accordance with any scroll effects.
- updateFreescrollBounds();
invalidate();
}
@Override
public void onChildViewRemoved(View parent, View child) {
- updateFreescrollBounds();
mCurrentPage = validateNewPage(mCurrentPage);
invalidate();
}
@@ -974,11 +958,6 @@
return offset;
}
- protected void getFreeScrollPageRange(int[] range) {
- range[0] = 0;
- range[1] = Math.max(0, getChildCount() - 1);
- }
-
@Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
int page = indexToPage(indexOfChild(child));
@@ -1349,29 +1328,12 @@
setEnableFreeScroll(false);
}
- void updateFreescrollBounds() {
- getFreeScrollPageRange(mTempVisiblePagesRange);
- if (mIsRtl) {
- mFreeScrollMinScrollX = getScrollForPage(mTempVisiblePagesRange[1]);
- mFreeScrollMaxScrollX = getScrollForPage(mTempVisiblePagesRange[0]);
- } else {
- mFreeScrollMinScrollX = getScrollForPage(mTempVisiblePagesRange[0]);
- mFreeScrollMaxScrollX = getScrollForPage(mTempVisiblePagesRange[1]);
- }
- }
-
private void setEnableFreeScroll(boolean freeScroll) {
boolean wasFreeScroll = mFreeScroll;
mFreeScroll = freeScroll;
if (mFreeScroll) {
- updateFreescrollBounds();
- getFreeScrollPageRange(mTempVisiblePagesRange);
- if (getCurrentPage() < mTempVisiblePagesRange[0]) {
- setCurrentPage(mTempVisiblePagesRange[0]);
- } else if (getCurrentPage() > mTempVisiblePagesRange[1]) {
- setCurrentPage(mTempVisiblePagesRange[1]);
- }
+ setCurrentPage(getNextPage());
} else if (wasFreeScroll) {
snapToPage(getNextPage());
}
@@ -1387,12 +1349,12 @@
if (mDragView != null) {
int dragX = (int) (mDragView.getLeft() + (mDragView.getMeasuredWidth() / 2)
+ mDragView.getTranslationX());
- getFreeScrollPageRange(mTempVisiblePagesRange);
int minDistance = Integer.MAX_VALUE;
int minIndex = indexOfChild(mDragView);
- for (int i = mTempVisiblePagesRange[0]; i <= mTempVisiblePagesRange[1]; i++) {
+ int maxPageNo = getChildCount() - 1;
+ for (int i = 0; i <= maxPageNo; i++) {
View page = getPageAt(i);
- int pageX = (int) (page.getLeft() + page.getMeasuredWidth() / 2);
+ int pageX = (page.getLeft() + page.getMeasuredWidth() / 2);
int d = Math.abs(dragX - pageX);
if (d < minDistance) {
minIndex = i;
@@ -1487,11 +1449,7 @@
final int pageUnderPointIndex = getNearestHoverOverPageIndex();
// Do not allow any page to be moved to 0th position.
if (pageUnderPointIndex > 0 && pageUnderPointIndex != indexOfChild(mDragView)) {
- mTempVisiblePagesRange[0] = 0;
- mTempVisiblePagesRange[1] = getPageCount() - 1;
- getFreeScrollPageRange(mTempVisiblePagesRange);
- if (mTempVisiblePagesRange[0] <= pageUnderPointIndex &&
- pageUnderPointIndex <= mTempVisiblePagesRange[1] &&
+ if (0 <= pageUnderPointIndex && pageUnderPointIndex <= getPageCount() - 1 &&
pageUnderPointIndex != mSidePageHoverIndex && mScroller.isFinished()) {
mSidePageHoverIndex = pageUnderPointIndex;
mSidePageHoverRunnable = new Runnable() {
@@ -2025,18 +1983,14 @@
// Do not allow the first page to be moved around
if (mTouchState != TOUCH_STATE_REST || dragViewIndex <= 0) return false;
- mTempVisiblePagesRange[0] = 0;
- mTempVisiblePagesRange[1] = getPageCount() - 1;
- getFreeScrollPageRange(mTempVisiblePagesRange);
- mReorderingStarted = true;
-
// Check if we are within the reordering range
- if (mTempVisiblePagesRange[0] <= dragViewIndex &&
- dragViewIndex <= mTempVisiblePagesRange[1]) {
+ if (0 <= dragViewIndex && dragViewIndex <= getPageCount() - 1) {
// Find the drag view under the pointer
mDragView = getChildAt(dragViewIndex);
mDragView.animate().scaleX(1.15f).scaleY(1.15f).setDuration(100).start();
mDragViewBaselineLeft = mDragView.getLeft();
+ mReorderingStarted = true;
+
snapToPage(getPageNearestToCenterOfScreen());
disableFreeScroll();
onStartReordering();
diff --git a/src/com/android/launcher3/PinchToOverviewListener.java b/src/com/android/launcher3/PinchToOverviewListener.java
index 407f0b5..d1a2538 100644
--- a/src/com/android/launcher3/PinchToOverviewListener.java
+++ b/src/com/android/launcher3/PinchToOverviewListener.java
@@ -16,27 +16,22 @@
package com.android.launcher3;
+import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+
import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.util.Range;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
+import com.android.launcher3.compat.AnimatorSetCompat;
import com.android.launcher3.util.TouchController;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
/**
* Detects pinches and animates the Workspace to/from overview mode.
*/
-@TargetApi(Build.VERSION_CODES.O)
public class PinchToOverviewListener
implements TouchController, OnScaleGestureListener, Runnable {
@@ -52,9 +47,8 @@
private Workspace mWorkspace = null;
private boolean mPinchStarted = false;
- private AnimatorSet mCurrentAnimation;
+ private AnimatorSetCompat mCurrentAnimation;
private float mCurrentScale;
- private Range<Integer> mDurationRange;
private boolean mShouldGoToFinalState;
private LauncherState mToState;
@@ -75,8 +69,8 @@
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
- if (!mLauncher.isInState(LauncherState.NORMAL)
- && !mLauncher.isInState(LauncherState.OVERVIEW)) {
+ if (!mLauncher.isInState(NORMAL)
+ && !mLauncher.isInState(OVERVIEW)) {
// Don't listen for the pinch gesture if on all apps, widget picker, -1, etc.
return false;
}
@@ -105,16 +99,14 @@
mLauncher.getDragController().cancelDrag();
}
- mToState = mLauncher.isInState(LauncherState.OVERVIEW)
- ? LauncherState.NORMAL : LauncherState.OVERVIEW;
- mCurrentAnimation = mLauncher.getStateTransition()
- .createAnimationToNewWorkspace(mToState, this);
+ mToState = mLauncher.isInState(OVERVIEW) ? NORMAL : OVERVIEW;
+ mCurrentAnimation = AnimatorSetCompat.wrap(mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(mToState, this), OVERVIEW_TRANSITION_MS);
mPinchStarted = true;
mCurrentScale = 1;
- mDurationRange = Range.create(0, LauncherAnimUtils.OVERVIEW_TRANSITION_MS);
mShouldGoToFinalState = false;
- dispatchOnStart(mCurrentAnimation);
+ mCurrentAnimation.dispatchOnStart();
return true;
}
@@ -132,11 +124,8 @@
mCurrentAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- if (mToState == LauncherState.OVERVIEW) {
- mLauncher.showWorkspace(false);
- } else {
- mLauncher.showOverviewMode(false);
- }
+ mLauncher.getStateManager().goToState(
+ mToState == OVERVIEW ? NORMAL : OVERVIEW, false);
}
});
mCurrentAnimation.reverse();
@@ -150,38 +139,18 @@
// If we are zooming out, inverse the mCurrentScale so that animationFraction = [0, 1]
// 0 => Animation complete
// 1=> Animation started
- float animationFraction = mToState ==
- LauncherState.OVERVIEW ? mCurrentScale : (1 / mCurrentScale);
+ float animationFraction = mToState == OVERVIEW ? mCurrentScale : (1 / mCurrentScale);
float velocity = (1 - detector.getScaleFactor()) / detector.getTimeDelta();
if (Math.abs(velocity) >= FLING_VELOCITY) {
- LauncherState toState = velocity > 0 ? LauncherState.OVERVIEW : LauncherState.NORMAL;
+ LauncherState toState = velocity > 0 ? OVERVIEW : NORMAL;
mShouldGoToFinalState = toState == mToState;
} else {
mShouldGoToFinalState = animationFraction <= ACCEPT_THRESHOLD;
}
// Move the transition animation to that duration.
- long playPosition = mDurationRange.clamp(
- (int) ((1 - animationFraction) * mDurationRange.getUpper()));
- mCurrentAnimation.setCurrentPlayTime(playPosition);
-
+ mCurrentAnimation.setPlayFraction(1 - animationFraction);
return true;
}
-
- private void dispatchOnStart(Animator animator) {
- for (AnimatorListener l : nonNullList(animator.getListeners())) {
- l.onAnimationStart(animator);
- }
-
- if (animator instanceof AnimatorSet) {
- for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
- dispatchOnStart(anim);
- }
- }
- }
-
- private static <T> List<T> nonNullList(ArrayList<T> list) {
- return list == null ? Collections.<T>emptyList() : list;
- }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 173ff6d..900e5bf 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -16,10 +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_DELAY;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.isAccessibilityEnabled;
import android.animation.Animator;
@@ -54,15 +56,13 @@
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.LauncherStateManager.AnimationConfig;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.OverviewAccessibilityDelegate;
import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate;
@@ -207,7 +207,7 @@
private final float[] mHotseatAlpha = new float[] {1, 1, 1};
@ViewDebug.ExportedProperty(category = "launcher")
- private LauncherState mState = LauncherState.NORMAL;
+ private LauncherState mState = NORMAL;
private boolean mIsSwitchingState = false;
boolean mChildrenLayersEnabled = true;
@@ -413,7 +413,7 @@
}
// Always enter the spring loaded mode
- mLauncher.enterSpringLoadedDragMode();
+ mLauncher.getStateManager().goToState(SPRING_LOADED);
}
public void deferRemoveExtraEmptyScreen() {
@@ -576,6 +576,7 @@
mWorkspaceScreens.put(screenId, newScreen);
mScreenOrder.add(insertIndex, screenId);
addView(newScreen, insertIndex);
+ mStateTransitionAnimation.applyChildState(mState, newScreen, insertIndex);
if (mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {
newScreen.enableAccessibleDrag(true, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG);
@@ -1343,7 +1344,7 @@
@Override
public void announceForAccessibility(CharSequence text) {
// Don't announce if apps is on top of us.
- if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
+ if (!mLauncher.isInState(ALL_APPS)) {
super.announceForAccessibility(text);
}
}
@@ -1411,12 +1412,12 @@
}
public boolean workspaceInModalState() {
- return mState != LauncherState.NORMAL;
+ return mState != NORMAL;
}
/** Returns whether a drag should be allowed to be started from the current workspace state. */
public boolean workspaceIconsCanBeDragged() {
- return mState == LauncherState.NORMAL || mState == LauncherState.SPRING_LOADED;
+ return mState == NORMAL || mState == SPRING_LOADED;
}
private void updateChildrenLayersEnabled() {
@@ -2015,7 +2016,7 @@
dropTargetLayout, mTargetCell, distance, false, d.dragView) ||
addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
distance, d, false)) {
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
return;
}
@@ -2130,7 +2131,7 @@
// spring-loaded mode so the page meets the icon where it was picked up.
mLauncher.getDragController().animateDragViewToOriginalPosition(
onCompleteRunnable, cell, SPRING_LOADED_TRANSITION_MS);
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
+ mLauncher.getStateManager().goToState(NORMAL);
mLauncher.getDropTargetBar().onDragEnd();
parent.onDropChild(cell);
return;
@@ -2153,8 +2154,8 @@
}
parent.onDropChild(cell);
- mLauncher.exitSpringLoadedDragMode(
- SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
+ mLauncher.getStateManager().goToState(
+ NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
}
if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
@@ -2686,7 +2687,7 @@
final long screenId = getIdForScreen(cellLayout);
if (!mLauncher.isHotseatLayout(cellLayout)
&& screenId != getScreenIdForPageIndex(mCurrentPage)
- && mState != LauncherState.SPRING_LOADED) {
+ && mState != SPRING_LOADED) {
snapToPage(getPageIndexForScreenId(screenId));
}
@@ -2761,7 +2762,7 @@
animationStyle, finalView, true);
} else {
// This is for other drag/drop cases, like dragging from All Apps
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
View view;
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index d66255b..0ccb8ad 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -32,7 +32,7 @@
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
-import com.android.launcher3.LauncherStateTransitionAnimation.AnimationConfig;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimationLayerSet;
/**
@@ -178,9 +178,6 @@
* Starts a transition animation for the workspace.
*/
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter) {
- // Update the workspace state
- int finalBackgroundAlpha = state.hasScrim ? 255 : 0;
-
float[] scaleAndTranslationY = state.getWorkspaceScaleAndTranslation(mLauncher);
mNewScale = scaleAndTranslationY[0];
final float finalWorkspaceTranslationY = scaleAndTranslationY[1];
@@ -188,16 +185,8 @@
int toPage = mWorkspace.getPageNearestToCenterOfScreen();
final int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
- final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
- propertySetter.setInt(cl.getScrimBackground(),
- DRAWABLE_ALPHA, finalBackgroundAlpha, mZoomInInterpolator);
-
- // Only animate the page alpha when we actually fade pages
- if (mWorkspaceFadeInAdjacentScreens) {
- float finalAlpha = state == LauncherState.NORMAL && i != toPage ? 0 : 1f;
- propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
- finalAlpha, mZoomInInterpolator);
- }
+ applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, toPage,
+ propertySetter);
}
float finalHotseatAlpha = state.hideHotseat ? 0f : 1f;
@@ -217,6 +206,24 @@
state.hasScrim ? mWorkspaceScrimAlpha : 0, new DecelerateInterpolator(1.5f));
}
+ public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
+ applyChildState(state, cl, childIndex, mWorkspace.getPageNearestToCenterOfScreen(),
+ NO_ANIM_PROPERTY_SETTER);
+ }
+
+ private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
+ int centerPage, PropertySetter propertySetter) {
+ propertySetter.setInt(cl.getScrimBackground(),
+ DRAWABLE_ALPHA, state.hasScrim ? 255 : 0, mZoomInInterpolator);
+
+ // Only animate the page alpha when we actually fade pages
+ if (mWorkspaceFadeInAdjacentScreens) {
+ float finalAlpha = state == LauncherState.NORMAL && childIndex != centerPage ? 0 : 1f;
+ propertySetter.setFloat(cl.getShortcutsAndWidgets(), View.ALPHA,
+ finalAlpha, mZoomInInterpolator);
+ }
+ }
+
private static class PropertySetter {
public void setViewAlpha(Animator anim, View view, float alpha) {
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index f17818a..512db72 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -1,5 +1,7 @@
package com.android.launcher3.accessibility;
+import static com.android.launcher3.LauncherState.NORMAL;
+
import android.app.AlertDialog;
import android.appwidget.AppWidgetProviderInfo;
import android.content.DialogInterface;
@@ -28,6 +30,7 @@
import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
@@ -150,14 +153,14 @@
} else if (action == ADD_TO_WORKSPACE) {
final int[] coordinates = new int[2];
final long screenId = findSpaceOnWorkspace(item, coordinates);
- mLauncher.showWorkspace(true, new Runnable() {
+ mLauncher.getStateManager().goToState(NORMAL, true, new Runnable() {
@Override
public void run() {
if (item instanceof AppInfo) {
ShortcutInfo info = ((AppInfo) item).makeShortcut();
mLauncher.getModelWriter().addItemToDatabase(info,
- LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
ArrayList<ItemInfo> itemList = new ArrayList<>();
@@ -167,7 +170,7 @@
PendingAddItemInfo info = (PendingAddItemInfo) item;
Workspace workspace = mLauncher.getWorkspace();
workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
- mLauncher.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+ mLauncher.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
screenId, coordinates, info.spanX, info.spanY);
}
announceConfirmation(R.string.item_added_to_workspace);
diff --git a/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java
index 29dd95c..771353e 100644
--- a/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/OverviewAccessibilityDelegate.java
@@ -24,6 +24,7 @@
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -55,7 +56,7 @@
public boolean performAccessibilityAction(View host, int action, Bundle args) {
Launcher launcher = Launcher.getLauncher(host.getContext());
if (action == OVERVIEW) {
- launcher.showOverviewMode(true);
+ launcher.getStateManager().goToState(LauncherState.OVERVIEW);
return true;
} else if (action == WALLPAPERS) {
launcher.onClickWallpaperPicker(host);
diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
index 5b7353a..cfb0520 100644
--- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
@@ -16,6 +16,8 @@
package com.android.launcher3.accessibility;
+import static com.android.launcher3.LauncherState.NORMAL;
+
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -79,9 +81,7 @@
}
};
- if (!mLauncher.showWorkspace(true, onComplete)) {
- onComplete.run();
- }
+ mLauncher.getStateManager().goToState(NORMAL, true, onComplete);
return true;
} else if (action == DISMISS_NOTIFICATION) {
if (!(host instanceof NotificationMainView)) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 35dfa81..d62cd4b 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -1,5 +1,8 @@
package com.android.launcher3.allapps;
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
@@ -19,7 +22,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateTransitionAnimation.AnimationConfig;
+import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
@@ -193,7 +196,7 @@
@Override
public void onDragStart(boolean start) {
mCaretController.onDragStart();
- mLauncher.getStateTransition().cancelAnimation();
+ mLauncher.getStateManager().cancelAnimation();
cancelDiscoveryAnimation();
mShiftStart = mAppsView.getTranslationY();
onProgressAnimationStart();
@@ -230,7 +233,7 @@
if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
logSwipeOnContainer(Touch.FLING, Direction.UP, containerType);
}
- mLauncher.showAppsView(true /* animated */);
+ mLauncher.getStateManager().goToState(ALL_APPS);
if (hasSpringAnimationHandler()) {
mSpringAnimationHandler.add(mSearchSpring, true /* setDefaultValues */);
// The icons are moving upwards, so we go to 0 from 1. (y-axis 1 is below 0.)
@@ -241,7 +244,7 @@
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
logSwipeOnContainer(Touch.FLING, Direction.DOWN, ContainerType.ALLAPPS);
}
- mLauncher.showWorkspace(true /* animated */);
+ mLauncher.getStateManager().goToState(NORMAL);
}
// snap to top or bottom using the release velocity
} else {
@@ -250,13 +253,13 @@
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
logSwipeOnContainer(Touch.SWIPE, Direction.DOWN, ContainerType.ALLAPPS);
}
- mLauncher.showWorkspace(true /* animated */);
+ mLauncher.getStateManager().goToState(NORMAL);
} else {
calculateDuration(velocity, Math.abs(mAppsView.getTranslationY()));
if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
logSwipeOnContainer(Touch.SWIPE, Direction.UP, containerType);
}
- mLauncher.showAppsView(true /* animated */);
+ mLauncher.getStateManager().goToState(ALL_APPS);
}
}
}
diff --git a/src/com/android/launcher3/compat/AnimatorSetCompat.java b/src/com/android/launcher3/compat/AnimatorSetCompat.java
new file mode 100644
index 0000000..497dd14
--- /dev/null
+++ b/src/com/android/launcher3/compat/AnimatorSetCompat.java
@@ -0,0 +1,204 @@
+/*
+ * 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.compat;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.view.animation.LinearInterpolator;
+
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimationSuccessListener;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Compat implementation for various new APIs in {@link AnimatorSet}
+ *
+ * Note: The compat implementation does not support start delays on child animations or
+ * sequential playbacks.
+ */
+public abstract class AnimatorSetCompat implements ValueAnimator.AnimatorUpdateListener {
+
+ public static AnimatorSetCompat wrap(AnimatorSet anim, int duration) {
+ if (Utilities.ATLEAST_OREO) {
+ return new AnimatorSetCompatVO(anim, duration);
+ } else {
+ return new AnimatorSetCompatVL(anim, duration);
+ }
+ }
+
+ private final ValueAnimator mAnimationPlayer;
+ private final long mDuration;
+
+ protected final AnimatorSet mAnim;
+
+ protected float mCurrentFraction;
+
+ protected AnimatorSetCompat(AnimatorSet anim, int duration) {
+ mAnim = anim;
+ mDuration = duration;
+
+ mAnimationPlayer = ValueAnimator.ofFloat(0, 1);
+ mAnimationPlayer.setInterpolator(new LinearInterpolator());
+ mAnimationPlayer.addUpdateListener(this);
+ }
+
+ /**
+ * Starts playing the animation forward from current position.
+ */
+ public void start() {
+ mAnimationPlayer.setFloatValues(mCurrentFraction, 1);
+ mAnimationPlayer.setDuration(clampDuration(1 - mCurrentFraction));
+ mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
+ mAnimationPlayer.start();
+ }
+
+ /**
+ * Starts playing the animation backwards from current position
+ */
+ public void reverse() {
+ mAnimationPlayer.setFloatValues(mCurrentFraction, 0);
+ mAnimationPlayer.setDuration(clampDuration(mCurrentFraction));
+ mAnimationPlayer.addListener(new OnAnimationEndDispatcher());
+ mAnimationPlayer.start();
+ }
+
+ /**
+ * Sets the current animation position and updates all the child animators accordingly.
+ */
+ public abstract void setPlayFraction(float fraction);
+
+ /**
+ * @see Animator#addListener(AnimatorListener)
+ */
+ public void addListener(Animator.AnimatorListener listener) {
+ mAnimationPlayer.addListener(listener);
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ setPlayFraction((float) valueAnimator.getAnimatedValue());
+ }
+
+ protected long clampDuration(float fraction) {
+ float playPos = mDuration * fraction;
+ if (playPos <= 0) {
+ return 0;
+ } else {
+ return Math.min((long) playPos, mDuration);
+ }
+ }
+
+ public void dispatchOnStart() {
+ dispatchOnStartRecursively(mAnim);
+ }
+
+ private void dispatchOnStartRecursively(Animator animator) {
+ for (AnimatorListener l : nonNullList(animator.getListeners())) {
+ l.onAnimationStart(animator);
+ }
+
+ if (animator instanceof AnimatorSet) {
+ for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
+ dispatchOnStartRecursively(anim);
+ }
+ }
+ }
+
+ public static class AnimatorSetCompatVL extends AnimatorSetCompat {
+
+ private final ValueAnimator[] mChildAnimations;
+
+ private AnimatorSetCompatVL(AnimatorSet anim, int duration) {
+ super(anim, duration);
+
+ // Build animation list
+ ArrayList<ValueAnimator> childAnims = new ArrayList<>();
+ getAnimationsRecur(mAnim, childAnims);
+ mChildAnimations = childAnims.toArray(new ValueAnimator[childAnims.size()]);
+ }
+
+ private void getAnimationsRecur(AnimatorSet anim, ArrayList<ValueAnimator> out) {
+ long forceDuration = anim.getDuration();
+ for (Animator child : anim.getChildAnimations()) {
+ if (forceDuration > 0) {
+ child.setDuration(forceDuration);
+ }
+ if (child instanceof ValueAnimator) {
+ out.add((ValueAnimator) child);
+ } else if (child instanceof AnimatorSet) {
+ getAnimationsRecur((AnimatorSet) child, out);
+ } else {
+ throw new RuntimeException("Unknown animation type " + child);
+ }
+ }
+ }
+
+ @Override
+ public void setPlayFraction(float fraction) {
+ mCurrentFraction = fraction;
+ long playPos = clampDuration(fraction);
+ for (ValueAnimator anim : mChildAnimations) {
+ anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
+ }
+ }
+
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private static class AnimatorSetCompatVO extends AnimatorSetCompat {
+
+ private AnimatorSetCompatVO(AnimatorSet anim, int duration) {
+ super(anim, duration);
+ }
+
+ @Override
+ public void setPlayFraction(float fraction) {
+ mCurrentFraction = fraction;
+ mAnim.setCurrentPlayTime(clampDuration(fraction));
+ }
+ }
+
+ private class OnAnimationEndDispatcher extends AnimationSuccessListener {
+
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ dispatchOnEndRecursively(mAnim);
+ }
+
+ private void dispatchOnEndRecursively(Animator animator) {
+ for (AnimatorListener l : nonNullList(animator.getListeners())) {
+ l.onAnimationEnd(animator);
+ }
+
+ if (animator instanceof AnimatorSet) {
+ for (Animator anim : nonNullList(((AnimatorSet) animator).getChildAnimations())) {
+ dispatchOnEndRecursively(anim);
+ }
+ }
+ }
+ }
+
+ private static <T> List<T> nonNullList(ArrayList<T> list) {
+ return list == null ? Collections.<T>emptyList() : list;
+ }
+}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 10bd67d..9402383 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -17,6 +17,7 @@
package com.android.launcher3.dragndrop;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
+import static com.android.launcher3.LauncherState.NORMAL;
import android.content.ComponentName;
import android.content.res.Resources;
@@ -263,7 +264,7 @@
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(SPRING_LOADED_EXIT_DELAY);
+ mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
mDragObject.deferDragViewCleanupPostAnimation = false;
}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index f2bad6b..bc5aafc 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -143,7 +143,7 @@
public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
- || !Utilities.ATLEAST_OREO ? null : new PinchToOverviewListener(mLauncher);
+ ? null : new PinchToOverviewListener(mLauncher);
}
public boolean isEventOverHotseat(MotionEvent ev) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index fcc4f0e..2168001 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -17,6 +17,7 @@
package com.android.launcher3.folder;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
+import static com.android.launcher3.LauncherState.NORMAL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -1243,7 +1244,7 @@
mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher.getModelWriter());
}
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_DELAY);
+ mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
if (d.stateAnnouncer != null) {
d.stateAnnouncer.completeAction(R.string.item_moved);
}
diff --git a/src/com/android/launcher3/states/AllAppsState.java b/src/com/android/launcher3/states/AllAppsState.java
index 9922d99..ee35b4d 100644
--- a/src/com/android/launcher3/states/AllAppsState.java
+++ b/src/com/android/launcher3/states/AllAppsState.java
@@ -19,8 +19,10 @@
import android.view.View;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
/**
@@ -41,6 +43,14 @@
if (!launcher.getSharedPrefs().getBoolean(APPS_VIEW_SHOWN, false)) {
launcher.getSharedPrefs().edit().putBoolean(APPS_VIEW_SHOWN, true).apply();
}
+
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ dispatchWindowStateChanged(launcher);
+ }
+
+ @Override
+ public String getDescription(Launcher launcher) {
+ return launcher.getString(R.string.all_apps_button_label);
}
@Override
diff --git a/src/com/android/launcher3/states/OverviewState.java b/src/com/android/launcher3/states/OverviewState.java
index 57f023c..344a4f9 100644
--- a/src/com/android/launcher3/states/OverviewState.java
+++ b/src/com/android/launcher3/states/OverviewState.java
@@ -36,8 +36,7 @@
// The percent to shrink the workspace during overview mode
public static final float SCALE_FACTOR = 0.7f;
- private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE | FLAG_HIDE_HOTSEAT |
- FLAG_DO_NOT_RESTORE;
+ private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE | FLAG_HIDE_HOTSEAT;
public OverviewState(int id) {
super(id, ContainerType.WORKSPACE, OVERVIEW_TRANSITION_MS, 1f, STATE_FLAGS);
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
index ec62764..fe0571b 100644
--- a/src/com/android/launcher3/util/FlingAnimation.java
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -1,6 +1,6 @@
package com.android.launcher3.util;
-import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_NEXT_FRAME;
+import static com.android.launcher3.LauncherState.NORMAL;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
@@ -97,7 +97,7 @@
Runnable onAnimationEndRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.exitSpringLoadedDragMode(SPRING_LOADED_EXIT_NEXT_FRAME);
+ mLauncher.getStateManager().goToState(NORMAL);
mDropTarget.completeDrop(mDragObject);
}
};