diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 6cfdcf70bc..9b4642d660 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -25,7 +25,6 @@ import android.graphics.Paint.FontMetrics; import android.graphics.Point; import android.graphics.Rect; import android.util.DisplayMetrics; -import android.util.Size; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -385,7 +384,7 @@ public class DeviceProfile { final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources()); // Layout the search bar space - View searchBar = launcher.getSearchBar(); + View searchBar = launcher.getSearchDropTargetBar(); lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); if (hasVerticalBarLayout) { // Vertical search bar space -- The search bar is fixed in the layout to be on the left diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index 8445cca3c9..f523c49867 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -160,7 +160,7 @@ public class DragLayer extends InsettableFrameLayout { } private boolean isEventOverDropTargetBar(MotionEvent ev) { - getDescendantRectRelativeToSelf(mLauncher.getSearchBar(), mHitRect); + getDescendantRectRelativeToSelf(mLauncher.getSearchDropTargetBar(), mHitRect); if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) { return true; } @@ -322,7 +322,7 @@ public class DragLayer extends InsettableFrameLayout { childrenForAccessibility.add(currentFolder); if (isInAccessibleDrag()) { - childrenForAccessibility.add(mLauncher.getSearchBar()); + childrenForAccessibility.add(mLauncher.getSearchDropTargetBar()); } } else { super.addChildrenForAccessibility(childrenForAccessibility); diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index fc59546661..79117354ab 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -275,7 +275,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Override public void enableAccessibleDrag(boolean enable) { - mLauncher.getSearchBar().enableAccessibleDrag(enable); + mLauncher.getSearchDropTargetBar().enableAccessibleDrag(enable); for (int i = 0; i < mContent.getChildCount(); i++) { mContent.getPageAt(i).enableAccessibleDrag(enable, CellLayout.FOLDER_ACCESSIBILITY_DRAG); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 6be6103201..40c7b29047 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -132,8 +132,7 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class Launcher extends Activity implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, - View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener, - LauncherStateTransitionAnimation.Callbacks { + View.OnTouchListener, PageSwitchListener, LauncherProviderChangeListener { static final String TAG = "Launcher"; static final boolean LOGD = false; @@ -448,7 +447,7 @@ public class Launcher extends Activity mDragController = new DragController(this); mInflater = getLayoutInflater(); - mStateTransitionAnimation = new LauncherStateTransitionAnimation(this, this); + mStateTransitionAnimation = new LauncherStateTransitionAnimation(this); mStats = new Stats(this); @@ -1816,7 +1815,7 @@ public class Launcher extends Activity return mOverviewPanel; } - public SearchDropTargetBar getSearchBar() { + public SearchDropTargetBar getSearchDropTargetBar() { return mSearchDropTargetBar; } @@ -3228,14 +3227,6 @@ public class Launcher extends Activity } } - @Override - public void onStateTransitionHideSearchBar() { - // Hide the search bar - if (mSearchDropTargetBar != null) { - mSearchDropTargetBar.hideSearchBar(false /* animated */); - } - } - public void showWorkspace(boolean animated) { showWorkspace(animated, null); } @@ -3244,16 +3235,9 @@ public class Launcher extends Activity boolean changed = mState != State.WORKSPACE || mWorkspace.getState() != Workspace.State.NORMAL; if (changed) { - boolean wasInSpringLoadedMode = (mState != State.WORKSPACE); mWorkspace.setVisibility(View.VISIBLE); - mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL, - animated, onCompleteRunnable); - - // Show the search bar (only animate if we were showing the drop target bar in spring - // loaded mode) - if (mSearchDropTargetBar != null) { - mSearchDropTargetBar.showSearchBar(animated && wasInSpringLoadedMode); - } + mStateTransitionAnimation.startAnimationToWorkspace(mState, mWorkspace.getState(), + Workspace.State.NORMAL, animated, onCompleteRunnable); // Set focus to the AppsCustomize button if (mAllAppsButton != null) { @@ -3277,8 +3261,8 @@ public class Launcher extends Activity void showOverviewMode(boolean animated) { mWorkspace.setVisibility(View.VISIBLE); - mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.OVERVIEW, - animated, null /* onCompleteRunnable */); + mStateTransitionAnimation.startAnimationToWorkspace(mState, mWorkspace.getState(), + Workspace.State.OVERVIEW, animated, null /* onCompleteRunnable */); mState = State.WORKSPACE; } @@ -3331,9 +3315,10 @@ public class Launcher extends Activity } if (toState == State.APPS) { - mStateTransitionAnimation.startAnimationToAllApps(animated, focusSearchBar); + mStateTransitionAnimation.startAnimationToAllApps(mWorkspace.getState(), animated, + focusSearchBar); } else { - mStateTransitionAnimation.startAnimationToWidgets(animated); + mStateTransitionAnimation.startAnimationToWidgets(mWorkspace.getState(), animated); } // Change the state *after* we've called all the transition code @@ -3355,10 +3340,9 @@ public class Launcher extends Activity * new state. */ public Animator startWorkspaceStateChangeAnimation(Workspace.State toState, - boolean animated, boolean hasOverlaySearchBar, HashMap layerViews) { + boolean animated, HashMap layerViews) { Workspace.State fromState = mWorkspace.getState(); - Animator anim = mWorkspace.setStateWithAnimation( - toState, animated, hasOverlaySearchBar, layerViews); + Animator anim = mWorkspace.setStateWithAnimation(toState, animated, layerViews); updateInteraction(fromState, toState); return anim; } @@ -3382,8 +3366,9 @@ public class Launcher extends Activity return; } - mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.SPRING_LOADED, - true /* animated */, null /* onCompleteRunnable */); + mStateTransitionAnimation.startAnimationToWorkspace(mState, mWorkspace.getState(), + Workspace.State.SPRING_LOADED, true /* animated */, + null /* onCompleteRunnable */); mState = isAppsViewVisible() ? State.APPS_SPRING_LOADED : State.WIDGETS_SPRING_LOADED; } @@ -4480,14 +4465,16 @@ public class Launcher extends Activity if (mWorkspace != null) mWorkspace.setAlpha(1f); if (mHotseat != null) mHotseat.setAlpha(1f); if (mPageIndicators != null) mPageIndicators.setAlpha(1f); - if (mSearchDropTargetBar != null) mSearchDropTargetBar.showSearchBar(false); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.animateToState( + SearchDropTargetBar.State.SEARCH_BAR, 0); } void hideWorkspaceSearchAndHotseat() { if (mWorkspace != null) mWorkspace.setAlpha(0f); if (mHotseat != null) mHotseat.setAlpha(0f); if (mPageIndicators != null) mPageIndicators.setAlpha(0f); - if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.animateToState( + SearchDropTargetBar.State.INVISIBLE, 0); } // TODO: These method should be a part of LauncherSearchCallback diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java index e49cd1c543..38bf04136f 100644 --- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java +++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java @@ -79,13 +79,6 @@ import java.util.HashMap; */ public class LauncherStateTransitionAnimation { - /** - * Callbacks made during the state transition - */ - interface Callbacks { - public void onStateTransitionHideSearchBar(); - } - /** * Private callbacks made during transition setup. */ @@ -111,12 +104,10 @@ public class LauncherStateTransitionAnimation { public static final int SINGLE_FRAME_DELAY = 16; @Thunk Launcher mLauncher; - @Thunk Callbacks mCb; - @Thunk AnimatorSet mStateAnimation; + @Thunk AnimatorSet mCurrentAnimation; - public LauncherStateTransitionAnimation(Launcher l, Callbacks cb) { + public LauncherStateTransitionAnimation(Launcher l) { mLauncher = l; - mCb = cb; } /** @@ -125,8 +116,8 @@ public class LauncherStateTransitionAnimation { * @param startSearchAfterTransition Immediately starts app search after the transition to * All Apps is completed. */ - public void startAnimationToAllApps(final boolean animated, - final boolean startSearchAfterTransition) { + public void startAnimationToAllApps(final Workspace.State fromWorkspaceState, + final boolean animated, final boolean startSearchAfterTransition) { final AllAppsContainerView toView = mLauncher.getAppsView(); final View buttonView = mLauncher.getAllAppsButton(); PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { @@ -159,15 +150,16 @@ public class LauncherStateTransitionAnimation { } }; // Only animate the search bar if animating from spring loaded mode back to all apps - startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, buttonView, toView, - toView.getContentView(), toView.getRevealView(), toView.getSearchBarView(), - animated, true /* hideSearchBar */, cb); + mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState, + Workspace.State.NORMAL_HIDDEN, buttonView, toView, toView.getContentView(), + toView.getRevealView(), toView.getSearchBarView(), animated, cb); } /** * Starts an animation to the widgets view. */ - public void startAnimationToWidgets(final boolean animated) { + public void startAnimationToWidgets(final Workspace.State fromWorkspaceState, + final boolean animated) { final WidgetsContainerView toView = mLauncher.getWidgetsView(); final View buttonView = mLauncher.getWidgetsButton(); PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { @@ -176,17 +168,17 @@ public class LauncherStateTransitionAnimation { return 0.3f; } }; - startAnimationToOverlay(Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, - toView.getContentView(), toView.getRevealView(), null, animated, - true /* hideSearchBar */, cb); + mCurrentAnimation = startAnimationToOverlay(fromWorkspaceState, + Workspace.State.OVERVIEW_HIDDEN, buttonView, toView, toView.getContentView(), + toView.getRevealView(), null, animated, cb); } /** * Starts and animation to the workspace from the current overlay view. */ public void startAnimationToWorkspace(final Launcher.State fromState, - final Workspace.State toWorkspaceState, - final boolean animated, final Runnable onCompleteRunnable) { + final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState, + final boolean animated, final Runnable onCompleteRunnable) { if (toWorkspaceState != Workspace.State.NORMAL && toWorkspaceState != Workspace.State.SPRING_LOADED && toWorkspaceState != Workspace.State.OVERVIEW) { @@ -194,9 +186,11 @@ public class LauncherStateTransitionAnimation { } if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) { - startAnimationToWorkspaceFromAllApps(toWorkspaceState, animated, onCompleteRunnable); + startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState, + animated, onCompleteRunnable); } else { - startAnimationToWorkspaceFromWidgets(toWorkspaceState, animated, onCompleteRunnable); + startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState, + animated, onCompleteRunnable); } } @@ -204,10 +198,11 @@ public class LauncherStateTransitionAnimation { * Creates and starts a new animation to a particular overlay view. */ @SuppressLint("NewApi") - private void startAnimationToOverlay(final Workspace.State toWorkspaceState, - final View buttonView, final View toView, final View contentView, final View revealView, - final View overlaySearchBarView, final boolean animated, final boolean hideSearchBar, - final PrivateTransitionCallbacks pCb) { + private AnimatorSet startAnimationToOverlay(final Workspace.State fromWorkspaceState, + final Workspace.State toWorkspaceState, final View buttonView, final View toView, + final View contentView, final View revealView, final View overlaySearchBarView, + final boolean animated, final PrivateTransitionCallbacks pCb) { + final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); final Resources res = mLauncher.getResources(); final boolean material = Utilities.isLmpOrAbove(); final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime); @@ -227,11 +222,13 @@ public class LauncherStateTransitionAnimation { // Create the workspace animation. // NOTE: this call apparently also sets the state for the workspace if !animated Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState, - animated, overlaySearchBarView != null /* hasOverlaySearchBar */, layerViews); + animated, layerViews); + + // Animate the search bar + startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState, + animated ? revealDuration : 0, overlaySearchBarView); if (animated && initialized) { - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - // Setup the reveal view animation int width = revealView.getMeasuredWidth(); int height = revealView.getMeasuredHeight(); @@ -271,7 +268,7 @@ public class LauncherStateTransitionAnimation { // Play the animation layerViews.put(revealView, BUILD_AND_SET_LAYER); - mStateAnimation.play(panelAlphaAndDrift); + animation.play(panelAlphaAndDrift); if (overlaySearchBarView != null) { overlaySearchBarView.setAlpha(0f); @@ -279,7 +276,7 @@ public class LauncherStateTransitionAnimation { searchBarAlpha.setDuration(100); searchBarAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER); - mStateAnimation.play(searchBarAlpha); + animation.play(searchBarAlpha); } // Setup the animation for the content view @@ -294,13 +291,13 @@ public class LauncherStateTransitionAnimation { pageDrift.setDuration(revealDuration); pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0)); pageDrift.setStartDelay(itemsAlphaStagger); - mStateAnimation.play(pageDrift); + animation.play(pageDrift); ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 0f, 1f); itemsAlpha.setDuration(revealDuration); itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); itemsAlpha.setStartDelay(itemsAlphaStagger); - mStateAnimation.play(itemsAlpha); + animation.play(itemsAlpha); if (material) { float startRadius = pCb.getMaterialRevealViewStartFinalRadius(); @@ -313,10 +310,10 @@ public class LauncherStateTransitionAnimation { if (listener != null) { reveal.addListener(listener); } - mStateAnimation.play(reveal); + animation.play(reveal); } - mStateAnimation.addListener(new AnimatorListenerAdapter() { + animation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { dispatchOnLauncherTransitionEnd(fromView, animated, false); @@ -332,12 +329,8 @@ public class LauncherStateTransitionAnimation { } } - if (hideSearchBar) { - mCb.onStateTransitionHideSearchBar(); - } - // This can hold unnecessary references to views. - mStateAnimation = null; + cleanupAnimation(); pCb.onTransitionComplete(); } @@ -345,7 +338,7 @@ public class LauncherStateTransitionAnimation { // Play the workspace animation if (workspaceAnim != null) { - mStateAnimation.play(workspaceAnim); + animation.play(workspaceAnim); } // Dispatch the prepare transition signal @@ -353,12 +346,12 @@ public class LauncherStateTransitionAnimation { dispatchOnLauncherTransitionPrepare(toView, animated, false); - final AnimatorSet stateAnimation = mStateAnimation; + final AnimatorSet stateAnimation = animation; final Runnable startAnimRunnable = new Runnable() { public void run() { - // Check that mStateAnimation hasn't changed while + // Check that mCurrentAnimation hasn't changed while // we waited for a layout/draw pass - if (mStateAnimation != stateAnimation) + if (mCurrentAnimation != stateAnimation) return; dispatchOnLauncherTransitionStart(fromView, animated, false); dispatchOnLauncherTransitionStart(toView, animated, false); @@ -377,12 +370,14 @@ public class LauncherStateTransitionAnimation { // Focus the new view toView.requestFocus(); - mStateAnimation.start(); + stateAnimation.start(); } }; toView.bringToFront(); toView.setVisibility(View.VISIBLE); toView.post(startAnimRunnable); + + return animation; } else { toView.setTranslationX(0.0f); toView.setTranslationY(0.0f); @@ -394,10 +389,6 @@ public class LauncherStateTransitionAnimation { // Show the content view contentView.setVisibility(View.VISIBLE); - if (hideSearchBar) { - mCb.onStateTransitionHideSearchBar(); - } - dispatchOnLauncherTransitionPrepare(fromView, animated, false); dispatchOnLauncherTransitionStart(fromView, animated, false); dispatchOnLauncherTransitionEnd(fromView, animated, false); @@ -405,18 +396,19 @@ public class LauncherStateTransitionAnimation { dispatchOnLauncherTransitionStart(toView, animated, false); dispatchOnLauncherTransitionEnd(toView, animated, false); pCb.onTransitionComplete(); + + return null; } } /** * Starts and animation to the workspace from the apps view. */ - private void startAnimationToWorkspaceFromAllApps(final Workspace.State toWorkspaceState, - final boolean animated, final Runnable onCompleteRunnable) { + private void startAnimationToWorkspaceFromAllApps(final Workspace.State fromWorkspaceState, + final Workspace.State toWorkspaceState, final boolean animated, + final Runnable onCompleteRunnable) { AllAppsContainerView appsView = mLauncher.getAppsView(); PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { - int[] mAllAppsToPanelDelta; - @Override float getMaterialRevealViewFinalAlpha(View revealView) { // No alpha anim from all apps @@ -448,16 +440,18 @@ public class LauncherStateTransitionAnimation { } }; // Only animate the search bar if animating to spring loaded mode from all apps - startAnimationToWorkspaceFromOverlay(toWorkspaceState, mLauncher.getAllAppsButton(), - appsView, appsView.getContentView(), appsView.getRevealView(), - appsView.getSearchBarView(), animated, onCompleteRunnable, cb); + mCurrentAnimation = startAnimationToWorkspaceFromOverlay(fromWorkspaceState, toWorkspaceState, + mLauncher.getAllAppsButton(), appsView, appsView.getContentView(), + appsView.getRevealView(), appsView.getSearchBarView(), animated, + onCompleteRunnable, cb); } /** * Starts and animation to the workspace from the widgets view. */ - private void startAnimationToWorkspaceFromWidgets(final Workspace.State toWorkspaceState, - final boolean animated, final Runnable onCompleteRunnable) { + private void startAnimationToWorkspaceFromWidgets(final Workspace.State fromWorkspaceState, + final Workspace.State toWorkspaceState, final boolean animated, + final Runnable onCompleteRunnable) { final WidgetsContainerView widgetsView = mLauncher.getWidgetsView(); PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { @Override @@ -475,18 +469,21 @@ public class LauncherStateTransitionAnimation { }; } }; - startAnimationToWorkspaceFromOverlay(toWorkspaceState, mLauncher.getWidgetsButton(), - widgetsView, widgetsView.getContentView(), widgetsView.getRevealView(), null, - animated, onCompleteRunnable, cb); - } + mCurrentAnimation = startAnimationToWorkspaceFromOverlay(fromWorkspaceState, + toWorkspaceState, mLauncher.getWidgetsButton(), widgetsView, + widgetsView.getContentView(), widgetsView.getRevealView(), null, animated, + onCompleteRunnable, cb); + } /** * Creates and starts a new animation to the workspace. */ - private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState, - final View buttonView, final View fromView, final View contentView, - final View revealView, final View overlaySearchBarView, final boolean animated, - final Runnable onCompleteRunnable, final PrivateTransitionCallbacks pCb) { + private AnimatorSet startAnimationToWorkspaceFromOverlay(final Workspace.State fromWorkspaceState, + final Workspace.State toWorkspaceState, final View buttonView, + final View fromView, final View contentView, final View revealView, + final View overlaySearchBarView, final boolean animated, final Runnable onCompleteRunnable, + final PrivateTransitionCallbacks pCb) { + final AnimatorSet animation = LauncherAnimUtils.createAnimatorSet(); final Resources res = mLauncher.getResources(); final boolean material = Utilities.isLmpOrAbove(); final int revealDuration = res.getInteger(R.integer.config_overlayRevealTime); @@ -506,15 +503,16 @@ public class LauncherStateTransitionAnimation { // Create the workspace animation. // NOTE: this call apparently also sets the state for the workspace if !animated Animator workspaceAnim = mLauncher.startWorkspaceStateChangeAnimation(toWorkspaceState, - animated, overlaySearchBarView != null /* hasOverlaySearchBar */, - layerViews); + animated, layerViews); + + // Animate the search bar + startWorkspaceSearchBarAnimation(animation, fromWorkspaceState, toWorkspaceState, + animated ? revealDuration : 0, overlaySearchBarView); if (animated && initialized) { - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - // Play the workspace animation if (workspaceAnim != null) { - mStateAnimation.play(workspaceAnim); + animation.play(workspaceAnim); } // hideAppsCustomizeHelper is called in some cases when it is already hidden @@ -553,14 +551,14 @@ public class LauncherStateTransitionAnimation { panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY); panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY); panelDriftY.setInterpolator(decelerateInterpolator); - mStateAnimation.play(panelDriftY); + animation.play(panelDriftY); ObjectAnimator panelDriftX = ObjectAnimator.ofFloat(revealView, "translationX", 0, revealViewToXDrift); panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY); panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY); panelDriftX.setInterpolator(decelerateInterpolator); - mStateAnimation.play(panelDriftX); + animation.play(panelDriftX); // Setup animation for the reveal panel alpha final float revealViewToAlpha = !material ? 0f : @@ -571,7 +569,7 @@ public class LauncherStateTransitionAnimation { panelAlpha.setDuration(material ? revealDuration : 150); panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY); panelAlpha.setInterpolator(decelerateInterpolator); - mStateAnimation.play(panelAlpha); + animation.play(panelAlpha); } // Setup the animation for the content view @@ -584,13 +582,13 @@ public class LauncherStateTransitionAnimation { pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY); pageDrift.setInterpolator(decelerateInterpolator); pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY); - mStateAnimation.play(pageDrift); + animation.play(pageDrift); contentView.setAlpha(1f); ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(contentView, "alpha", 1f, 0f); itemsAlpha.setDuration(100); itemsAlpha.setInterpolator(decelerateInterpolator); - mStateAnimation.play(itemsAlpha); + animation.play(itemsAlpha); if (overlaySearchBarView != null) { overlaySearchBarView.setAlpha(1f); @@ -599,7 +597,7 @@ public class LauncherStateTransitionAnimation { searchAlpha.setInterpolator(decelerateInterpolator); searchAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY); layerViews.put(overlaySearchBarView, BUILD_AND_SET_LAYER); - mStateAnimation.play(searchAlpha); + animation.play(searchAlpha); } if (material) { @@ -615,14 +613,14 @@ public class LauncherStateTransitionAnimation { if (listener != null) { reveal.addListener(listener); } - mStateAnimation.play(reveal); + animation.play(reveal); } dispatchOnLauncherTransitionPrepare(fromView, animated, true); dispatchOnLauncherTransitionPrepare(toView, animated, true); } - mStateAnimation.addListener(new AnimatorListenerAdapter() { + animation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { fromView.setVisibility(View.GONE); @@ -652,18 +650,19 @@ public class LauncherStateTransitionAnimation { } // This can hold unnecessary references to views. - mStateAnimation = null; + cleanupAnimation(); pCb.onTransitionComplete(); } }); - final AnimatorSet stateAnimation = mStateAnimation; + final AnimatorSet stateAnimation = animation; final Runnable startAnimRunnable = new Runnable() { public void run() { - // Check that mStateAnimation hasn't changed while + // Check that mCurrentAnimation hasn't changed while // we waited for a layout/draw pass - if (mStateAnimation != stateAnimation) + if (mCurrentAnimation != stateAnimation) return; + dispatchOnLauncherTransitionStart(fromView, animated, false); dispatchOnLauncherTransitionStart(toView, animated, false); @@ -677,10 +676,12 @@ public class LauncherStateTransitionAnimation { v.buildLayer(); } } - mStateAnimation.start(); + stateAnimation.start(); } }; fromView.post(startAnimRunnable); + + return animation; } else { fromView.setVisibility(View.GONE); dispatchOnLauncherTransitionPrepare(fromView, animated, true); @@ -695,9 +696,44 @@ public class LauncherStateTransitionAnimation { if (onCompleteRunnable != null) { onCompleteRunnable.run(); } + + return null; } } + /** + * Coordinates the workspace search bar animation along with the launcher state animation. + */ + private void startWorkspaceSearchBarAnimation(AnimatorSet animation, + final Workspace.State fromWorkspaceState, final Workspace.State toWorkspaceState, int duration, + View overlaySearchBar) { + final SearchDropTargetBar.State toSearchBarState = + toWorkspaceState.getSearchDropTargetBarState(); + + if (overlaySearchBar != null) { + if ((toWorkspaceState == Workspace.State.NORMAL) && + (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN)) { + // If we are transitioning from the overlay to the workspace, then show the + // workspace search bar immediately and let the overlay search bar fade out on top + mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0); + } else if (fromWorkspaceState == Workspace.State.NORMAL) { + // If we are transitioning from the workspace to the overlay, then keep the + // workspace search bar visible until the overlay search bar fades in on top + animation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, 0); + } + }); + } else { + // Otherwise, then just animate the workspace search bar normally + mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration); + } + } else { + // If there is no overlay search bar, then just animate the workspace search bar + mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState, duration); + } + } /** * Dispatches the prepare-transition event to suitable views. @@ -748,10 +784,14 @@ public class LauncherStateTransitionAnimation { * Cancels the current animation. */ private void cancelAnimation() { - if (mStateAnimation != null) { - mStateAnimation.setDuration(0); - mStateAnimation.cancel(); - mStateAnimation = null; + if (mCurrentAnimation != null) { + mCurrentAnimation.setDuration(0); + mCurrentAnimation.cancel(); + mCurrentAnimation = null; } } + + private void cleanupAnimation() { + mCurrentAnimation = null; + } } diff --git a/src/com/android/launcher3/LauncherViewPropertyAnimator.java b/src/com/android/launcher3/LauncherViewPropertyAnimator.java index 4cafbbfa66..4406a2c5cb 100644 --- a/src/com/android/launcher3/LauncherViewPropertyAnimator.java +++ b/src/com/android/launcher3/LauncherViewPropertyAnimator.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.EnumSet; public class LauncherViewPropertyAnimator extends Animator implements AnimatorListener { + enum Properties { TRANSLATION_X, TRANSLATION_Y, @@ -51,13 +52,12 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi long mStartDelay; long mDuration; TimeInterpolator mInterpolator; - ArrayList mListeners; + ArrayList mListeners = new ArrayList<>(); boolean mRunning = false; FirstFrameAnimatorHelper mFirstFrameHelper; public LauncherViewPropertyAnimator(View target) { mTarget = target; - mListeners = new ArrayList(); } @Override diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java index 824acad15a..15c942a50c 100644 --- a/src/com/android/launcher3/SearchDropTargetBar.java +++ b/src/com/android/launcher3/SearchDropTargetBar.java @@ -18,12 +18,11 @@ package com.android.launcher3; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; +import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; @@ -33,17 +32,41 @@ import android.widget.FrameLayout; */ public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener { - private static final int TRANSITION_DURATION = 200; + /** The different states that the search bar space can be in. */ + public enum State { + INVISIBLE (0f, 0f), + SEARCH_BAR (1f, 0f), + DROP_TARGET (0f, 1f); - private ObjectAnimator mShowDropTargetBarAnim; - private ValueAnimator mHideSearchBarAnim; + private final float mSearchBarAlpha; + private final float mDropTargetBarAlpha; + + State(float sbAlpha, float dtbAlpha) { + mSearchBarAlpha = sbAlpha; + mDropTargetBarAlpha = dtbAlpha; + } + + float getSearchBarAlpha() { + return mSearchBarAlpha; + } + + float getDropTargetBarAlpha() { + return mDropTargetBarAlpha; + } + } + + private static int DEFAULT_DRAG_FADE_DURATION = 175; + + private LauncherViewPropertyAnimator mDropTargetBarAnimator; + private LauncherViewPropertyAnimator mQSBSearchBarAnimator; private static final AccelerateInterpolator sAccelerateInterpolator = new AccelerateInterpolator(); - private boolean mIsSearchBarHidden; - private View mQSBSearchBar; + private State mState = State.SEARCH_BAR; + private View mQSB; private View mDropTargetBar; private boolean mDeferOnDragEnd = false; + private boolean mAccessibilityEnabled = false; // Drop targets private ButtonDropTarget mInfoDropTarget; @@ -75,39 +98,6 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D mUninstallDropTarget.setLauncher(launcher); } - public void setQsbSearchBar(View qsb) { - mQSBSearchBar = qsb; - if (mQSBSearchBar != null) { - mHideSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, ALPHA, 1f, 0f); - setupAnimation(mHideSearchBarAnim, mQSBSearchBar); - } else { - // Create a no-op animation of the search bar is null - mHideSearchBarAnim = ValueAnimator.ofFloat(0, 0); - mHideSearchBarAnim.setDuration(TRANSITION_DURATION); - } - } - - private void prepareStartAnimation(View v) { - // Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd - // callback below) - if (v != null) { - v.setLayerType(View.LAYER_TYPE_HARDWARE, null); - } - } - - private void setupAnimation(ValueAnimator anim, final View v) { - anim.setInterpolator(sAccelerateInterpolator); - anim.setDuration(TRANSITION_DURATION); - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (v != null) { - v.setLayerType(View.LAYER_TYPE_NONE, null); - } - } - }); - } - @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -124,72 +114,84 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D // Create the various fade animations mDropTargetBar.setAlpha(0f); - mShowDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, ALPHA, 0f, 1f); - setupAnimation(mShowDropTargetBarAnim, mDropTargetBar); + mDropTargetBarAnimator = new LauncherViewPropertyAnimator(mDropTargetBar); + mDropTargetBarAnimator.setInterpolator(sAccelerateInterpolator); + mDropTargetBarAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + // Ensure that the view is visible for the animation + mDropTargetBar.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mDropTargetBar != null) { + AlphaUpdateListener.updateVisibility(mDropTargetBar, mAccessibilityEnabled); + } + } + }); } - /** - * Finishes all the animations on the search and drop target bars. - */ - public void finishAnimations() { - prepareStartAnimation(mDropTargetBar); - mShowDropTargetBarAnim.reverse(); - prepareStartAnimation(mQSBSearchBar); - mHideSearchBarAnim.reverse(); - } + public void setQsbSearchBar(View qsb) { + mQSB = qsb; + if (mQSB != null) { + // Update the search ber animation + mQSBSearchBarAnimator = new LauncherViewPropertyAnimator(mQSB); + mQSBSearchBarAnimator.setInterpolator(sAccelerateInterpolator); + mQSBSearchBarAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + // Ensure that the view is visible for the animation + if (mQSB != null) { + mQSB.setVisibility(View.VISIBLE); + } + } - /** - * Shows the search bar. - */ - public void showSearchBar(boolean animated) { - if (!mIsSearchBarHidden) return; - if (animated) { - prepareStartAnimation(mQSBSearchBar); - mHideSearchBarAnim.reverse(); + @Override + public void onAnimationEnd(Animator animation) { + if (mQSB != null) { + AlphaUpdateListener.updateVisibility(mQSB, mAccessibilityEnabled); + } + } + }); } else { - mHideSearchBarAnim.cancel(); - if (mQSBSearchBar != null) { - mQSBSearchBar.setAlpha(1f); + mQSBSearchBarAnimator = null; + } + } + + /** + * Animates the current search bar state to a new state. If the {@param duration} is 0, then + * the state is applied immediately. + */ + public void animateToState(State newState, int duration) { + if (mState != newState) { + mState = newState; + + // Update the accessibility state + AccessibilityManager am = (AccessibilityManager) + getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); + mAccessibilityEnabled = am.isEnabled(); + + animateViewAlpha(mQSBSearchBarAnimator, mQSB, newState.getSearchBarAlpha(), + duration); + animateViewAlpha(mDropTargetBarAnimator, mDropTargetBar, newState.getDropTargetBarAlpha(), + duration); + } + } + + /** + * Convenience method to animate the alpha of a view using hardware layers. + */ + private void animateViewAlpha(LauncherViewPropertyAnimator animator, View v, float alpha, + int duration) { + if (v != null && Float.compare(v.getAlpha(), alpha) != 0) { + if (duration > 0) { + animator.alpha(alpha).withLayer().setDuration(duration).start(); + } else { + v.setAlpha(alpha); + AlphaUpdateListener.updateVisibility(v, mAccessibilityEnabled); } } - mIsSearchBarHidden = false; - } - - /** - * Hides the search bar. We only use this for clings. - */ - public void hideSearchBar(boolean animated) { - if (mIsSearchBarHidden) return; - if (animated) { - prepareStartAnimation(mQSBSearchBar); - mHideSearchBarAnim.start(); - } else { - mHideSearchBarAnim.cancel(); - if (mQSBSearchBar != null) { - mQSBSearchBar.setAlpha(0f); - } - } - mIsSearchBarHidden = true; - } - - /** - * Shows the drop target bar. - */ - public void showDeleteTarget() { - // Animate out the QSB search bar, and animate in the drop target bar - prepareStartAnimation(mDropTargetBar); - mShowDropTargetBarAnim.start(); - hideSearchBar(true); - } - - /** - * Hides the drop target bar. - */ - public void hideDeleteTarget() { - // Restore the QSB search bar, and animate out the drop target bar - prepareStartAnimation(mDropTargetBar); - mShowDropTargetBarAnim.reverse(); - showSearchBar(true); } /* @@ -197,9 +199,13 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D */ @Override public void onDragStart(DragSource source, ItemInfo info, int dragAction) { - showDeleteTarget(); + animateToState(State.DROP_TARGET, DEFAULT_DRAG_FADE_DURATION); } + /** + * This is called to defer hiding the delete drop target until the drop animation has completed, + * instead of hiding immediately when the drag has ended. + */ public void deferOnDragEnd() { mDeferOnDragEnd = true; } @@ -207,22 +213,25 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D @Override public void onDragEnd() { if (!mDeferOnDragEnd) { - hideDeleteTarget(); + animateToState(State.SEARCH_BAR, DEFAULT_DRAG_FADE_DURATION); } else { mDeferOnDragEnd = false; } } + /** + * @return the bounds of the QSB search bar. + */ public Rect getSearchBarBounds() { - if (mQSBSearchBar != null) { + if (mQSB != null) { final int[] pos = new int[2]; - mQSBSearchBar.getLocationOnScreen(pos); + mQSB.getLocationOnScreen(pos); final Rect rect = new Rect(); rect.left = pos[0]; rect.top = pos[1]; - rect.right = pos[0] + mQSBSearchBar.getWidth(); - rect.bottom = pos[1] + mQSBSearchBar.getHeight(); + rect.right = pos[0] + mQSB.getWidth(); + rect.bottom = pos[1] + mQSB.getHeight(); return rect; } else { return null; @@ -230,8 +239,8 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D } public void enableAccessibleDrag(boolean enable) { - if (mQSBSearchBar != null) { - mQSBSearchBar.setVisibility(enable ? View.GONE : View.VISIBLE); + if (mQSB != null) { + mQSB.setVisibility(enable ? View.GONE : View.VISIBLE); } mInfoDropTarget.enableAccessibleDrag(enable); mDeleteDropTarget.enableAccessibleDrag(enable); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index cb844bb79d..1fbc779b4d 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -178,7 +178,24 @@ public class Workspace extends PagedView // State variable that indicates whether the pages are small (ie when you're // in all apps or customize mode) - enum State { NORMAL, NORMAL_HIDDEN, SPRING_LOADED, OVERVIEW, OVERVIEW_HIDDEN}; + enum State { + NORMAL (SearchDropTargetBar.State.SEARCH_BAR), + NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE), + SPRING_LOADED (SearchDropTargetBar.State.DROP_TARGET), + OVERVIEW (SearchDropTargetBar.State.INVISIBLE), + OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE); + + private final SearchDropTargetBar.State mBarState; + + State(SearchDropTargetBar.State searchBarState) { + mBarState = searchBarState; + } + + public SearchDropTargetBar.State getSearchDropTargetBarState() { + return mBarState; + } + }; + private State mState = State.NORMAL; private boolean mIsSwitchingState = false; @@ -1558,7 +1575,7 @@ public class Workspace extends PagedView // Reset our click listener setOnClickListener(mLauncher); } - mLauncher.getSearchBar().enableAccessibleDrag(enable); + mLauncher.getSearchDropTargetBar().enableAccessibleDrag(enable); mLauncher.getHotseat().getLayout() .enableAccessibleDrag(enable, CellLayout.WORKSPACE_ACCESSIBILITY_DRAG); } @@ -1976,10 +1993,10 @@ public class Workspace extends PagedView * to that new state. */ public Animator setStateWithAnimation(State toState, boolean animated, - boolean hasOverlaySearchBar, HashMap layerViews) { + HashMap layerViews) { // Create the animation to the new state Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(mState, - toState, animated, hasOverlaySearchBar, layerViews); + toState, animated, layerViews); // Update the current state mState = toState; diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 652b19479d..f0975851dd 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -221,14 +221,13 @@ public class WorkspaceStateTransitionAnimation { } public AnimatorSet getAnimationToState(Workspace.State fromState, Workspace.State toState, - boolean animated, boolean hasOverlaySearchBar, HashMap layerViews) { + boolean animated, HashMap layerViews) { AccessibilityManager am = (AccessibilityManager) mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE); final boolean accessibilityEnabled = am.isEnabled(); TransitionStates states = new TransitionStates(fromState, toState); - int duration = getAnimationDuration(states); - animateWorkspace(states, animated, duration, layerViews, accessibilityEnabled); - animateSearchBar(states, animated, duration, hasOverlaySearchBar, layerViews, + int workspaceDuration = getAnimationDuration(states); + animateWorkspace(states, animated, workspaceDuration, layerViews, accessibilityEnabled); animateBackgroundGradient(states, animated, BACKGROUND_FADE_OUT_DURATION); return mStateAnimator; @@ -469,76 +468,10 @@ public class WorkspaceStateTransitionAnimation { } } - /** - * Coordinates with the workspace animation to animate the search bar. - * - * TODO: This should really be coordinated with the SearchDropTargetBar, otherwise the - * bar has no idea that it is hidden, and this has no idea what state the bar is - * actually in. - */ - private void animateSearchBar(TransitionStates states, boolean animated, int duration, - boolean hasOverlaySearchBar, final HashMap layerViews, - final boolean accessibilityEnabled) { - - // The search bar is only visible in the workspace - final View searchBar = mLauncher.getOrCreateQsbBar(); - if (searchBar != null) { - final boolean searchBarWillBeShown = states.stateIsNormal; - final float finalSearchBarAlpha = searchBarWillBeShown ? 1f : 0f; - if (animated) { - if (hasOverlaySearchBar) { - // If there is an overlay search bar, then we will coordinate with it. - mStateAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - // If we are transitioning to a visible search bar, show it immediately - // and let the overlay search bar has faded out - if (searchBarWillBeShown) { - searchBar.setAlpha(finalSearchBarAlpha); - AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled); - } - } - - @Override - public void onAnimationEnd(Animator animation) { - // If we are transitioning to a hidden search bar, hide it only after - // the overlay search bar has faded in - if (!searchBarWillBeShown) { - searchBar.setAlpha(finalSearchBarAlpha); - AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled); - } - } - }); - } else { - // Otherwise, we can just do the normal animation - LauncherViewPropertyAnimator searchBarAlpha = - new LauncherViewPropertyAnimator(searchBar).alpha(finalSearchBarAlpha); - searchBarAlpha.addListener(new AlphaUpdateListener(searchBar, - accessibilityEnabled)); - searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null); - if (layerViews != null) { - // If layerViews is not null, we add these views, and indicate that - // the caller can manage layer state. - layerViews.put(searchBar, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER); - } else { - // Otherwise let the animator handle layer management. - searchBarAlpha.withLayer(); - } - searchBarAlpha.setDuration(duration); - mStateAnimator.play(searchBarAlpha); - } - } else { - // Set the search bar state immediately - searchBar.setAlpha(finalSearchBarAlpha); - AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled); - } - } - } - /** * Animates the background scrim. Add to the state animator to prevent jankiness. * - * @param finalAlpha the final alpha for the background scrim + * @param states the current and final workspace states * @param animated whether or not to set the background alpha immediately * @duration duration of the animation */