private AnimatorSet mStateAnimation;
static final int APPWIDGET_HOST_ID = 1024;
- private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
- private static final int EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT = 600;
+ public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
+ private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
private static final int SHOW_CLING_DURATION = 250;
private static final int DISMISS_CLING_DURATION = 200;
// Reset the startActivity waiting flag
mWaitingForResult = false;
+ Runnable exitSpringLoaded = new Runnable() {
+ @Override
+ public void run() {
+ exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
+ EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ };
+
if (requestCode == REQUEST_BIND_APPWIDGET) {
- int appWidgetId = data != null ?
+ final int appWidgetId = data != null ?
data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
if (resultCode == RESULT_CANCELED) {
completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
} else if (resultCode == RESULT_OK) {
- addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, mPendingAddWidgetInfo);
+ addAppWidgetImpl(appWidgetId, mPendingAddInfo, null,
+ mPendingAddWidgetInfo, ON_ACTIVITY_RESULT_ANIMATION_DELAY);
}
return;
} else if (requestCode == REQUEST_PICK_WALLPAPER) {
return;
}
- boolean delayExitSpringLoadedMode = false;
boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
requestCode == REQUEST_CREATE_APPWIDGET);
// We have special handling for widgets
if (isWidgetDrop) {
- int appWidgetId = data != null ?
+ final int appWidgetId = data != null ?
data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
+ final int result;
+ final Runnable onComplete;
if (appWidgetId < 0) {
Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\" +
"widget configuration activity.");
- completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
- mWorkspace.stripEmptyScreens();
+ result = RESULT_CANCELED;
+ completeTwoStageWidgetDrop(result, appWidgetId);
+ onComplete = new Runnable() {
+ @Override
+ public void run() {
+ exitSpringLoadedDragModeDelayed(false, 0, null);
+ }
+ };
} else {
- completeTwoStageWidgetDrop(resultCode, appWidgetId);
+ result = resultCode;
+ onComplete = new Runnable() {
+ @Override
+ public void run() {
+ completeTwoStageWidgetDrop(result, appWidgetId);
+ }
+ };
}
+ mWorkspace.removeExtraEmptyScreen(true, onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY,
+ false);
return;
}
if (isWorkspaceLocked()) {
sPendingAddList.add(args);
} else {
- delayExitSpringLoadedMode = completeAdd(args);
+ completeAdd(args);
}
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
} else if (resultCode == RESULT_CANCELED) {
- mWorkspace.stripEmptyScreens();
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
}
mDragLayer.clearAnimatedView();
- // Exit spring loaded mode if necessary after cancelling the configuration of a widget
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), delayExitSpringLoadedMode,
- null);
}
private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
public void run() {
completeAddAppWidget(appWidgetId, mPendingAddInfo.container,
mPendingAddInfo.screenId, layout, null);
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
+ exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
+ EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
}
};
} else if (resultCode == RESULT_CANCELED) {
animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION;
- onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
- }
- };
}
if (mDragLayer.getAnimatedView() != null) {
mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout,
(DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
animationType, boundWidget, true);
- } else {
+ } else if (onCompleteRunnable != null) {
// The animated view may be null in the case of a rotation during widget configuration
onCompleteRunnable.run();
}
mPendingAddInfo.dropPos = null;
}
- void addAppWidgetImpl(final int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget,
- AppWidgetProviderInfo appWidgetInfo) {
+ void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
+ final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo) {
+ addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0);
+ }
+
+ void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
+ final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo, int
+ delay) {
if (appWidgetInfo.configure != null) {
mPendingAddWidgetInfo = appWidgetInfo;
Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise just add it
+ Runnable onComplete = new Runnable() {
+ @Override
+ public void run() {
+ // Exit spring loaded mode if necessary after adding the widget
+ exitSpringLoadedDragModeDelayed(true, EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT,
+ null);
+ }
+ };
completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
appWidgetInfo);
- // Exit spring loaded mode if necessary after adding the widget
- exitSpringLoadedDragModeDelayed(true, false, null);
+ mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false);
}
}
}
}
- void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, boolean extendedDelay,
+ void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay,
final Runnable onCompleteRunnable) {
if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED) return;
exitSpringLoadedDragMode();
}
}
- }, (extendedDelay ?
- EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT :
- EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT));
+ }, delay);
+
}
void exitSpringLoadedDragMode() {
}
// Remove the extra empty screen
- mWorkspace.removeExtraEmptyScreen();
+ mWorkspace.removeExtraEmptyScreen(false, null);
if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
addedApps != null && mAppsCustomizeContent != null) {
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
+ protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
+ protected static final int FADE_EMPTY_SCREEN_DURATION = 150;
+
private static final int BACKGROUND_FADE_OUT_DURATION = 350;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
private static final int FLING_THRESHOLD_VELOCITY = 500;
private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>();
private ArrayList<Long> mScreenOrder = new ArrayList<Long>();
+ private Runnable mRemoveEmptyScreenRunnable;
+
/**
* CellInfo for the cell that is currently being dragged
*/
InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
- removeExtraEmptyScreen();
mDragSourceInternal = null;
mLauncher.onInteractionEnd();
}
boolean lastChildOnScreen = false;
boolean childOnFinalScreen = false;
+ // Cancel any pending removal of empty screen
+ mRemoveEmptyScreenRunnable = null;
+
if (mDragSourceInternal != null) {
if (mDragSourceInternal.getChildCount() == 1) {
lastChildOnScreen = true;
return false;
}
- public void removeExtraEmptyScreen() {
+ private void convertFinalScreenToEmptyScreenIfNecessary() {
+ if (hasExtraEmptyScreen() || mScreenOrder.size() == 0) return;
+ long finalScreenId = mScreenOrder.get(mScreenOrder.size() - 1);
+
+ if (finalScreenId == CUSTOM_CONTENT_SCREEN_ID) return;
+ CellLayout finalScreen = mWorkspaceScreens.get(finalScreenId);
+
+ // If the final screen is empty, convert it to the extra empty screen
+ if (finalScreen.getShortcutsAndWidgets().getChildCount() == 0) {
+ mWorkspaceScreens.remove(finalScreenId);
+ mScreenOrder.remove(finalScreenId);
+
+ // if this is the last non-custom content screen, convert it to the empty screen
+ mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen);
+ mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
+ }
+ }
+
+ public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete) {
+ removeExtraEmptyScreen(animate, onComplete, 0, false);
+ }
+
+ public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete,
+ final int delay, final boolean stripEmptyScreens) {
+ if (delay > 0) {
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ removeExtraEmptyScreen(animate, onComplete, 0, stripEmptyScreens);
+ }
+
+ }, delay);
+ return;
+ }
+
+ convertFinalScreenToEmptyScreenIfNecessary();
if (hasExtraEmptyScreen()) {
- CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
- mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID);
- mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID);
- removeView(cl);
+ int emptyIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
+ if (getNextPage() == emptyIndex) {
+ snapToPage(getNextPage() - 1, SNAP_OFF_EMPTY_SCREEN_DURATION);
+ fadeAndRemoveEmptyScreen(SNAP_OFF_EMPTY_SCREEN_DURATION, FADE_EMPTY_SCREEN_DURATION,
+ onComplete, stripEmptyScreens);
+ } else {
+ fadeAndRemoveEmptyScreen(0, FADE_EMPTY_SCREEN_DURATION,
+ onComplete, stripEmptyScreens);
+ }
+ return;
}
+ if (onComplete != null) {
+ onComplete.run();
+ }
+ }
+
+ private void fadeAndRemoveEmptyScreen(int delay, int duration, final Runnable onComplete,
+ final boolean stripEmptyScreens) {
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+ PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 0f);
+
+ final CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
+
+ mRemoveEmptyScreenRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (hasExtraEmptyScreen()) {
+ mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID);
+ mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID);
+ removeView(cl);
+ if (stripEmptyScreens) {
+ stripEmptyScreens();
+ }
+ }
+ }
+ };
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(cl, alpha, bgAlpha);
+ oa.setDuration(duration);
+ oa.setStartDelay(delay);
+ oa.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mRemoveEmptyScreenRunnable != null) {
+ mRemoveEmptyScreenRunnable.run();
+ }
+ if (onComplete != null) {
+ onComplete.run();
+ }
+ }
+ });
+ oa.start();
}
public boolean hasExtraEmptyScreen() {
removeView(cl);
} else {
// if this is the last non-custom content screen, convert it to the empty screen
+ mRemoveEmptyScreenRunnable = null;
mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, cl);
mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
}
}
protected void snapToPage(int whichPage, Runnable r) {
+ snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION, r);
+ }
+
+ protected void snapToPage(int whichPage, int duration, Runnable r) {
if (mDelayedSnapToPageRunnable != null) {
mDelayedSnapToPageRunnable.run();
}
mDelayedSnapToPageRunnable = r;
- snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
+ snapToPage(whichPage, duration);
}
protected void snapToScreenId(long screenId, Runnable r) {
// cell also contains a shortcut, then create a folder with the two shortcuts.
if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
return;
}
if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
distance, d, false)) {
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
return;
}
if (finalResizeRunnable != null) {
finalResizeRunnable.run();
}
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
}
};
mAnimatingViewIntoPlace = true;
final Runnable exitSpringLoadedRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.exitSpringLoadedDragModeDelayed(true, false, null);
+ removeExtraEmptyScreen(false, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ });
}
};
external, scalePreview);
Resources res = mLauncher.getResources();
- int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
+ final int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
// In the case where we've prebound the widget, we remove it from the DragLayer
if (finalView instanceof AppWidgetHostView && external) {
final boolean isFlingToDelete, final boolean success) {
if (mDeferDropAfterUninstall) {
mDeferredAction = new Runnable() {
- public void run() {
- onDropCompleted(target, d, isFlingToDelete, success);
- mDeferredAction = null;
- }
- };
+ public void run() {
+ onDropCompleted(target, d, isFlingToDelete, success);
+ mDeferredAction = null;
+ }
+ };
return;
}
// If we move the item to anything not on the Workspace, check if any empty
// screens need to be removed. If we dropped back on the workspace, this will
// be done post drop animation.
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
}
} else if (mDragInfo != null) {
CellLayout cellLayout;