diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher3/PagedView.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/PinchAnimationManager.java | 285 | ||||
-rw-r--r-- | src/com/android/launcher3/PinchThresholdManager.java | 77 | ||||
-rw-r--r-- | src/com/android/launcher3/PinchToOverviewListener.java | 179 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 12 | ||||
-rw-r--r-- | src/com/android/launcher3/dragndrop/DragLayer.java | 17 |
7 files changed, 573 insertions, 0 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2d52341a7..fc828da7b 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3136,6 +3136,7 @@ public class Launcher extends Activity getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } + @Override public boolean onLongClick(View v) { if (!isDraggingEnabled()) return false; if (isWorkspaceLocked()) return false; diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index bc15338eb..fc8bb4507 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -1445,6 +1445,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mLastMotionXRemainder = 0; onScrollInteractionBegin(); pageBeginMoving(); + // Stop listening for things like pinches. + requestDisallowInterceptTouchEvent(true); } } diff --git a/src/com/android/launcher3/PinchAnimationManager.java b/src/com/android/launcher3/PinchAnimationManager.java new file mode 100644 index 000000000..3302cb652 --- /dev/null +++ b/src/com/android/launcher3/PinchAnimationManager.java @@ -0,0 +1,285 @@ +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.util.Log; +import android.view.View; + +import static com.android.launcher3.Workspace.State.NORMAL; +import static com.android.launcher3.Workspace.State.OVERVIEW; + +/** + * Manages the animations that play as the user pinches to/from overview mode. + * + * It will look like this pinching in: + * - Workspace scales down + * - At some threshold 1, hotseat and QSB fade out (full animation) + * - At a later threshold 2, panel buttons fade in and scrim fades in + * - At a final threshold 3, snap to overview + * + * Pinching out: + * - Workspace scales up + * - At threshold 1, panel buttons fade out + * - At threshold 2, hotseat and QSB fade in and scrim fades out + * - At threshold 3, snap to workspace + * + * @see PinchToOverviewListener + * @see PinchThresholdManager + */ +public class PinchAnimationManager { + private static final String TAG = "PinchAnimationManager"; + + private static final int THRESHOLD_ANIM_DURATION = 150; + + private Launcher mLauncher; + private Workspace mWorkspace; + + private float mOverviewScale; + private float mOverviewTranslationY; + private int mNormalOverviewTransitionDuration; + private final int[] mVisiblePageRange = new int[2]; + private boolean mIsAnimating; + + // Animators + private Animator mShowPageIndicatorAnimator; + private Animator mShowHotseatAnimator; + private Animator mShowOverviewPanelButtonsAnimator; + private Animator mShowScrimAnimator; + private Animator mHidePageIndicatorAnimator; + private Animator mHideHotseatAnimator; + private Animator mHideOverviewPanelButtonsAnimator; + private Animator mHideScrimAnimator; + + public PinchAnimationManager(Launcher launcher) { + mLauncher = launcher; + mWorkspace = launcher.mWorkspace; + + mOverviewScale = mWorkspace.getOverviewModeShrinkFactor(); + mOverviewTranslationY = mWorkspace.getOverviewModeTranslationY(); + mNormalOverviewTransitionDuration = mWorkspace.getStateTransitionAnimation() + .mOverviewTransitionTime; + + initializeAnimators(); + } + + private void initializeAnimators() { + mShowPageIndicatorAnimator = new LauncherViewPropertyAnimator( + mWorkspace.getPageIndicator()).alpha(1f).withLayer(); + mShowPageIndicatorAnimator.setInterpolator(null); + + mShowHotseatAnimator = new LauncherViewPropertyAnimator(mLauncher.getHotseat()) + .alpha(1f).withLayer(); + mShowHotseatAnimator.setInterpolator(null); + + mShowOverviewPanelButtonsAnimator = new LauncherViewPropertyAnimator( + mLauncher.getOverviewPanel()).alpha(1f).withLayer(); + mShowOverviewPanelButtonsAnimator.setInterpolator(null); + + mShowScrimAnimator = ObjectAnimator.ofFloat(mLauncher.getDragLayer(), "backgroundAlpha", + mWorkspace.getStateTransitionAnimation().mWorkspaceScrimAlpha); + mShowScrimAnimator.setInterpolator(null); + + mHidePageIndicatorAnimator = new LauncherViewPropertyAnimator( + mWorkspace.getPageIndicator()).alpha(0f).withLayer(); + mHidePageIndicatorAnimator.setInterpolator(null); + mHidePageIndicatorAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mWorkspace.getPageIndicator() != null) { + mWorkspace.getPageIndicator().setVisibility(View.INVISIBLE); + } + } + }); + + mHideHotseatAnimator = new LauncherViewPropertyAnimator(mLauncher.getHotseat()) + .alpha(0f).withLayer(); + mHideHotseatAnimator.setInterpolator(null); + mHideHotseatAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getHotseat().setVisibility(View.INVISIBLE); + } + }); + + mHideOverviewPanelButtonsAnimator = new LauncherViewPropertyAnimator( + mLauncher.getOverviewPanel()).alpha(0f).withLayer(); + mHideOverviewPanelButtonsAnimator.setInterpolator(null); + mHideOverviewPanelButtonsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getOverviewPanel().setVisibility(View.INVISIBLE); + } + }); + + mHideScrimAnimator = ObjectAnimator.ofFloat(mLauncher.getDragLayer(), "backgroundAlpha", 0f); + mHideScrimAnimator.setInterpolator(null); + } + + public int getNormalOverviewTransitionDuration() { + return mNormalOverviewTransitionDuration; + } + + /** + * Interpolate from {@param currentProgress} to {@param toProgress}, calling + * {@link #setAnimationProgress(float)} throughout the duration. If duration is -1, + * the default overview transition duration is used. + */ + public void animateToProgress(float currentProgress, float toProgress, int duration, + final PinchThresholdManager thresholdManager) { + if (duration == -1) { + duration = mNormalOverviewTransitionDuration; + } + ValueAnimator animator = ValueAnimator.ofFloat(currentProgress, toProgress); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float pinchProgress = (Float) animation.getAnimatedValue(); + setAnimationProgress(pinchProgress); + thresholdManager.updateAndAnimatePassedThreshold(pinchProgress, + PinchAnimationManager.this); + } + } + ); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsAnimating = false; + thresholdManager.reset(); + } + }); + animator.setDuration(duration).start(); + mIsAnimating = true; + } + + public boolean isAnimating() { + return mIsAnimating; + } + + /** + * Animates to the specified progress. This should be called repeatedly throughout the pinch + * gesture to run animations that interpolate throughout the gesture. + * @param interpolatedProgress The progress from 0 to 1, where 0 is overview and 1 is workspace. + */ + public void setAnimationProgress(float interpolatedProgress) { + float interpolatedScale = interpolatedProgress * (1f - mOverviewScale) + mOverviewScale; + float interpolatedTranslationY = (1f - interpolatedProgress) * mOverviewTranslationY; + mWorkspace.setScaleX(interpolatedScale); + mWorkspace.setScaleY(interpolatedScale); + mWorkspace.setTranslationY(interpolatedTranslationY); + setOverviewPanelsAlpha(1f - interpolatedProgress, 0); + + // Make sure adjacent pages, except custom content page, are visible while scaling. + mWorkspace.setCustomContentVisibility(View.INVISIBLE); + mWorkspace.invalidate(); + } + + /** + * Animates certain properties based on which threshold was passed, and in what direction. The + * starting state must also be taken into account because the thresholds mean different things + * when going from workspace to overview and vice versa. + * @param threshold One of {@link PinchThresholdManager#THRESHOLD_ONE}, + * {@link PinchThresholdManager#THRESHOLD_TWO}, or + * {@link PinchThresholdManager#THRESHOLD_THREE} + * @param startState {@link Workspace.State#NORMAL} or {@link Workspace.State#OVERVIEW}. + * @param goingTowards {@link Workspace.State#NORMAL} or {@link Workspace.State#OVERVIEW}. + * Note that this doesn't have to be the opposite of startState; + */ + public void animateThreshold(float threshold, Workspace.State startState, + Workspace.State goingTowards) { + if (threshold == PinchThresholdManager.THRESHOLD_ONE) { + if (startState == OVERVIEW) { + animateOverviewPanelButtons(goingTowards == OVERVIEW); + } else if (startState == NORMAL) { + animateHotseatAndPageIndicator(goingTowards == NORMAL); + animateQsb(goingTowards == NORMAL); + } + } else if (threshold == PinchThresholdManager.THRESHOLD_TWO) { + if (startState == OVERVIEW) { + animateHotseatAndPageIndicator(goingTowards == NORMAL); + animateQsb(goingTowards == NORMAL); + animateScrim(goingTowards == OVERVIEW); + } else if (startState == NORMAL) { + animateOverviewPanelButtons(goingTowards == OVERVIEW); + animateScrim(goingTowards == OVERVIEW); + } + } else if (threshold == PinchThresholdManager.THRESHOLD_THREE) { + // Passing threshold 3 ends the pinch and snaps to the new state. + if (startState == OVERVIEW && goingTowards == NORMAL) { + mLauncher.showWorkspace(true); + mWorkspace.snapToPage(mWorkspace.getPageNearestToCenterOfScreen()); + } else if (startState == NORMAL && goingTowards == OVERVIEW) { + mLauncher.showOverviewMode(true); + } + } else { + Log.e(TAG, "Received unknown threshold to animate: " + threshold); + } + } + + private void setOverviewPanelsAlpha(float alpha, int duration) { + mWorkspace.getVisiblePages(mVisiblePageRange); + for (int i = mVisiblePageRange[0]; i <= mVisiblePageRange[1]; i++) { + View page = mWorkspace.getPageAt(i); + if (!mWorkspace.shouldDrawChild(page)) { + continue; + } + if (duration == 0) { + ((CellLayout) page).setBackgroundAlpha(alpha); + } else { + ObjectAnimator.ofFloat(page, "backgroundAlpha", alpha) + .setDuration(duration).start(); + } + } + } + + private void animateHotseatAndPageIndicator(boolean show) { + if (show) { + mLauncher.getHotseat().setVisibility(View.VISIBLE); + mShowHotseatAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + if (mWorkspace.getPageIndicator() != null) { + // There aren't page indicators in landscape mode on phones, hence the null check. + mWorkspace.getPageIndicator().setVisibility(View.VISIBLE); + mShowPageIndicatorAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + } + } else { + mHideHotseatAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + if (mWorkspace.getPageIndicator() != null) { + // There aren't page indicators in landscape mode on phones, hence the null check. + mHidePageIndicatorAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + } + } + } + + private void animateQsb(boolean show) { + SearchDropTargetBar.State searchBarState = show ? SearchDropTargetBar.State.SEARCH_BAR + : SearchDropTargetBar.State.INVISIBLE; + mLauncher.getSearchDropTargetBar().animateToState(searchBarState, THRESHOLD_ANIM_DURATION); + } + + private void animateOverviewPanelButtons(boolean show) { + if (show) { + mLauncher.getOverviewPanel().setVisibility(View.VISIBLE); + mShowOverviewPanelButtonsAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + } else { + mHideOverviewPanelButtonsAnimator.setDuration(THRESHOLD_ANIM_DURATION).start(); + } + } + + private void animateScrim(boolean show) { + // We reninitialize the animators here so that they have the correct start values. + if (show) { + mShowScrimAnimator = ObjectAnimator.ofFloat(mLauncher.getDragLayer(), "backgroundAlpha", + mWorkspace.getStateTransitionAnimation().mWorkspaceScrimAlpha); + mShowScrimAnimator.setInterpolator(null); + mShowScrimAnimator.setDuration(mNormalOverviewTransitionDuration).start(); + } else { + mHideScrimAnimator.setupStartValues(); + mHideScrimAnimator = ObjectAnimator.ofFloat(mLauncher.getDragLayer(), "backgroundAlpha", + 0f); + mHideScrimAnimator.setInterpolator(null); + mHideScrimAnimator.setDuration(mNormalOverviewTransitionDuration).start(); + mHideScrimAnimator.setDuration(mNormalOverviewTransitionDuration).start(); + } + } +} diff --git a/src/com/android/launcher3/PinchThresholdManager.java b/src/com/android/launcher3/PinchThresholdManager.java new file mode 100644 index 000000000..d79a63174 --- /dev/null +++ b/src/com/android/launcher3/PinchThresholdManager.java @@ -0,0 +1,77 @@ +package com.android.launcher3; + +/** + * Keeps track of when thresholds are passed during a pinch gesture, + * used to inform {@link PinchAnimationManager} throughout. + * + * @see PinchToOverviewListener + * @see PinchAnimationManager + */ +public class PinchThresholdManager { + public static final float THRESHOLD_ZERO = 0.0f; + public static final float THRESHOLD_ONE = 0.40f; + public static final float THRESHOLD_TWO = 0.70f; + public static final float THRESHOLD_THREE = 0.95f; + + private Workspace mWorkspace; + + private float mPassedThreshold = THRESHOLD_ZERO; + + public PinchThresholdManager(Workspace workspace) { + mWorkspace = workspace; + } + + /** + * Uses the pinch progress to determine whether a threshold has been passed, + * and asks the {@param animationManager} to animate if so. + * @param progress From 0 to 1, where 0 is overview and 1 is workspace. + * @param animationManager Animates the threshold change if one is passed. + * @return The last passed threshold, one of + * {@link PinchThresholdManager#THRESHOLD_ZERO}, + * {@link PinchThresholdManager#THRESHOLD_ONE}, + * {@link PinchThresholdManager#THRESHOLD_TWO}, or + * {@link PinchThresholdManager#THRESHOLD_THREE} + */ + public float updateAndAnimatePassedThreshold(float progress, + PinchAnimationManager animationManager) { + if (!mWorkspace.isInOverviewMode()) { + // Invert the progress, because going from workspace to overview is 1 to 0. + progress = 1f - progress; + } + + float previousPassedThreshold = mPassedThreshold; + + if (progress < THRESHOLD_ONE) { + mPassedThreshold = THRESHOLD_ZERO; + } else if (progress < THRESHOLD_TWO) { + mPassedThreshold = THRESHOLD_ONE; + } else if (progress < THRESHOLD_THREE) { + mPassedThreshold = THRESHOLD_TWO; + } else { + mPassedThreshold = THRESHOLD_THREE; + } + + if (mPassedThreshold != previousPassedThreshold) { + Workspace.State fromState = mWorkspace.isInOverviewMode() ? Workspace.State.OVERVIEW + : Workspace.State.NORMAL; + Workspace.State toState = mWorkspace.isInOverviewMode() ? Workspace.State.NORMAL + : Workspace.State.OVERVIEW; + float thresholdToAnimate = mPassedThreshold; + if (mPassedThreshold < previousPassedThreshold) { + // User reversed pinch, so heading back to the state that they started from. + toState = fromState; + thresholdToAnimate = previousPassedThreshold; + } + animationManager.animateThreshold(thresholdToAnimate, fromState, toState); + } + return mPassedThreshold; + } + + public float getPassedThreshold() { + return mPassedThreshold; + } + + public void reset() { + mPassedThreshold = THRESHOLD_ZERO; + } +} diff --git a/src/com/android/launcher3/PinchToOverviewListener.java b/src/com/android/launcher3/PinchToOverviewListener.java new file mode 100644 index 000000000..ef4748528 --- /dev/null +++ b/src/com/android/launcher3/PinchToOverviewListener.java @@ -0,0 +1,179 @@ +package com.android.launcher3; + +import android.animation.TimeInterpolator; +import android.content.Context; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; + +/** + * Detects pinches and animates the Workspace to/from overview mode. + * + * Usage: Pass MotionEvents to onInterceptTouchEvent() and onTouchEvent(). This class will handle + * the pinch detection, and use {@link PinchAnimationManager} to handle the animations. + * + * @see PinchThresholdManager + * @see PinchAnimationManager + */ +public class PinchToOverviewListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + private static final float OVERVIEW_PROGRESS = 0f; + private static final float WORKSPACE_PROGRESS = 1f; + + private ScaleGestureDetector mPinchDetector; + private Launcher mLauncher; + private Workspace mWorkspace = null; + private boolean mPinchStarted = false; + private float mPreviousProgress; + private float mProgressDelta; + private long mPreviousTimeMillis; + private long mTimeDelta; + private boolean mPinchCanceled = false; + private TimeInterpolator mInterpolator; + + private PinchThresholdManager mThresholdManager; + private PinchAnimationManager mAnimationManager; + + public PinchToOverviewListener(Launcher launcher) { + mLauncher = launcher; + mPinchDetector = new ScaleGestureDetector((Context) mLauncher, this); + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + mPinchDetector.onTouchEvent(ev); + return mPinchStarted; + } + + public void onTouchEvent(MotionEvent ev) { + if (mPinchStarted) { + if (ev.getPointerCount() > 2) { + // Using more than two fingers causes weird behavior, so just cancel the pinch. + cancelPinch(mPreviousProgress, -1); + } else { + mPinchDetector.onTouchEvent(ev); + } + } + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + if (mLauncher.mState != Launcher.State.WORKSPACE || mLauncher.isOnCustomContent()) { + // Don't listen for the pinch gesture if on all apps, widget picker, -1, etc. + return false; + } + if (mAnimationManager != null && mAnimationManager.isAnimating()) { + // Don't listen for the pinch gesture if we are already animating from a previous one. + return false; + } + if (mWorkspace == null) { + mWorkspace = mLauncher.mWorkspace; + mThresholdManager = new PinchThresholdManager(mWorkspace); + mAnimationManager = new PinchAnimationManager(mLauncher); + } + if (mWorkspace.isSwitchingState() || mWorkspace.mScrollInteractionBegan) { + // Don't listen to pinches occurring while switching state, as it will cause a jump + // once the state switching animation is complete. + return false; + } + + mPreviousProgress = mWorkspace.isInOverviewMode() ? OVERVIEW_PROGRESS : WORKSPACE_PROGRESS; + mPreviousTimeMillis = System.currentTimeMillis(); + mInterpolator = mWorkspace.isInOverviewMode() ? new LogDecelerateInterpolator(100, 0) + : new LogAccelerateInterpolator(100, 0); + mPinchStarted = true; + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + super.onScaleEnd(detector); + + float passedThreshold = mThresholdManager.getPassedThreshold(); + // If we are going towards overview, mPreviousProgress is how much further we need to + // go, since it is going from 1 to 0. If we are going to workspace, we want + // 1 - mPreviousProgress. + float remainingProgress = mPreviousProgress; + if (mWorkspace.isInOverviewMode() || passedThreshold < PinchThresholdManager.THRESHOLD_ONE) { + remainingProgress = 1f - mPreviousProgress; + } + int duration = computeDuration(remainingProgress, mProgressDelta, mTimeDelta); + + if (passedThreshold < PinchThresholdManager.THRESHOLD_ONE) { + cancelPinch(mPreviousProgress, duration); + } else if (passedThreshold < PinchThresholdManager.THRESHOLD_THREE) { + float toProgress = mWorkspace.isInOverviewMode() ? + WORKSPACE_PROGRESS : OVERVIEW_PROGRESS; + mAnimationManager.animateToProgress(mPreviousProgress, toProgress, duration, + mThresholdManager); + } else { + mThresholdManager.reset(); + } + mPinchStarted = false; + mPinchCanceled = false; + } + + /** + * Compute the amount of time required to complete the transition based on the current pinch + * speed. If this time is too long, instead return the normal duration, ignoring the speed. + */ + private int computeDuration(float remainingProgress, float progressDelta, long timeDelta) { + float progressSpeed = Math.abs(progressDelta) / timeDelta; + int remainingMillis = (int) (remainingProgress / progressSpeed); + return Math.min(remainingMillis, mAnimationManager.getNormalOverviewTransitionDuration()); + } + + /** + * Cancels the current pinch, returning back to where the pinch started (either workspace or + * overview). If duration is -1, the default overview transition duration is used. + */ + private void cancelPinch(float currentProgress, int duration) { + if (mPinchCanceled) return; + mPinchCanceled = true; + float toProgress = mWorkspace.isInOverviewMode() ? OVERVIEW_PROGRESS : WORKSPACE_PROGRESS; + mAnimationManager.animateToProgress(currentProgress, toProgress, duration, + mThresholdManager); + mPinchStarted = false; + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + if (mThresholdManager.getPassedThreshold() == PinchThresholdManager.THRESHOLD_THREE) { + // We completed the pinch, so stop listening to further movement until user lets go. + return true; + } + if (mLauncher.getDragController().isDragging()) { + mLauncher.getDragController().cancelDrag(); + } + + float pinchDist = detector.getCurrentSpan() - detector.getPreviousSpan(); + if (pinchDist < 0 && mWorkspace.isInOverviewMode() || + pinchDist > 0 && !mWorkspace.isInOverviewMode()) { + // Pinching the wrong way, so ignore. + return false; + } + // Pinch distance must equal the workspace width before switching states. + int pinchDistanceToCompleteTransition = mWorkspace.getWidth(); + float overviewScale = mWorkspace.getOverviewModeShrinkFactor(); + float initialWorkspaceScale = mWorkspace.isInOverviewMode() ? overviewScale : 1f; + float pinchScale = initialWorkspaceScale + pinchDist / pinchDistanceToCompleteTransition; + // Bound the scale between the overview scale and the normal workspace scale (1f). + pinchScale = Math.max(overviewScale, Math.min(pinchScale, 1f)); + // Progress ranges from 0 to 1, where 0 corresponds to the overview scale and 1 + // corresponds to the normal workspace scale (1f). + float progress = (pinchScale - overviewScale) / (1f - overviewScale); + float interpolatedProgress = mInterpolator.getInterpolation(progress); + + mAnimationManager.setAnimationProgress(interpolatedProgress); + float passedThreshold = mThresholdManager.updateAndAnimatePassedThreshold( + interpolatedProgress, mAnimationManager); + if (passedThreshold == PinchThresholdManager.THRESHOLD_THREE) { + return true; + } + + mProgressDelta = interpolatedProgress - mPreviousProgress; + mPreviousProgress = interpolatedProgress; + mTimeDelta = System.currentTimeMillis() - mPreviousTimeMillis; + mPreviousTimeMillis = System.currentTimeMillis(); + return false; + } + + +}
\ No newline at end of file diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 0f8d834da..a74fa0dbc 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1900,6 +1900,10 @@ public class Workspace extends PagedView return -(workspaceHeight - scaledHeight) / 2; } + float getOverviewModeShrinkFactor() { + return mOverviewModeShrinkFactor; + } + /** * Sets the current workspace {@link State}, returning an animation transitioning the workspace * to that new state. @@ -1996,6 +2000,10 @@ public class Workspace extends PagedView void updateCustomContentVisibility() { int visibility = mState == Workspace.State.NORMAL ? VISIBLE : INVISIBLE; + setCustomContentVisibility(visibility); + } + + void setCustomContentVisibility(int visibility) { if (hasCustomContent()) { mWorkspaceScreens.get(CUSTOM_CONTENT_SCREEN_ID).setVisibility(visibility); } @@ -3526,6 +3534,10 @@ public class Workspace extends PagedView } } + public WorkspaceStateTransitionAnimation getStateTransitionAnimation() { + return mStateTransitionAnimation; + } + /** * Return the current {@link CellLayout}, correctly picking the destination * screen while a scroll is in progress. diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index f16a56c8b..647ec5e9f 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -47,6 +47,7 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetHostView; +import com.android.launcher3.PinchToOverviewListener; import com.android.launcher3.R; import com.android.launcher3.SearchDropTargetBar; import com.android.launcher3.ShortcutAndWidgetContainer; @@ -110,6 +111,8 @@ public class DragLayer extends InsettableFrameLayout { private Drawable mLeftHoverDrawableActive; private Drawable mRightHoverDrawableActive; + // Related to pinch-to-go-to-overview gesture. + private PinchToOverviewListener mPinchListener; /** * Used to create a new DragLayer from XML. * @@ -134,6 +137,8 @@ public class DragLayer extends InsettableFrameLayout { public void setup(Launcher launcher, DragController controller) { mLauncher = launcher; mDragController = controller; + + mPinchListener = new PinchToOverviewListener(mLauncher); } @Override @@ -241,6 +246,14 @@ public class DragLayer extends InsettableFrameLayout { mTouchCompleteListener = null; } clearAllResizeFrames(); + + Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); + if (currentFolder == null) { + if (mPinchListener.onInterceptTouchEvent(ev)) { + // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.) + return true; + } + } return mDragController.onInterceptTouchEvent(ev); } @@ -354,6 +367,10 @@ public class DragLayer extends InsettableFrameLayout { int x = (int) ev.getX(); int y = (int) ev.getY(); + // This is only reached if a pinch was started from onInterceptTouchEvent(); + // this continues sending events for it. + mPinchListener.onTouchEvent(ev); + if (action == MotionEvent.ACTION_DOWN) { if (handleTouchDown(ev, false)) { return true; |