diff options
-rw-r--r-- | src/com/android/launcher2/AppsCustomizeTabHost.java | 26 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 139 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedView.java | 5 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedViewGridLayout.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 96 |
5 files changed, 142 insertions, 125 deletions
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java index 2963240fa..023946b26 100644 --- a/src/com/android/launcher2/AppsCustomizeTabHost.java +++ b/src/com/android/launcher2/AppsCustomizeTabHost.java @@ -54,7 +54,6 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona private boolean mInTransition; private boolean mResetAfterTransition; - private Animator mLauncherTransition; public AppsCustomizeTabHost(Context context, AttributeSet attrs) { super(context, attrs); @@ -341,29 +340,17 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona } } - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (mLauncherTransition != null) { - enableAndBuildHardwareLayer(); - mLauncherTransition.start(); - mLauncherTransition = null; - } + @Override + public View getContent() { + return mContent; } /* LauncherTransitionable overrides */ @Override - public boolean onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) { + public void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) { mInTransition = true; - boolean delayLauncherTransitionUntilLayout = false; boolean animated = (animation != null); - mLauncherTransition = null; - // if the content wasn't visible before, delay the launcher animation until after a call - // to layout -- this prevents a blip - if (animated && mContent.getVisibility() == GONE) { - mLauncherTransition = animation; - delayLauncherTransitionUntilLayout = true; - } mContent.setVisibility(VISIBLE); if (!toWorkspace) { @@ -371,7 +358,7 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona // transition to prevent slowing down the animation) mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true); } - if (animated && !delayLauncherTransitionUntilLayout) { + if (animated) { enableAndBuildHardwareLayer(); } @@ -382,7 +369,6 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona mAppsCustomizePane.reset(); mResetAfterTransition = false; } - return delayLauncherTransitionUntilLayout; } @Override @@ -406,7 +392,7 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona } } - public void onResume() { + public void onWindowVisible() { if (getVisibility() == VISIBLE) { mContent.setVisibility(VISIBLE); // We unload the widget previews when the UI is hidden, so need to reload pages diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 15da5017f..5abfa2856 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -28,7 +28,6 @@ import android.app.ActivityManager; import android.app.AlertDialog; import android.app.Dialog; import android.app.SearchManager; -import android.app.StatusBarManager; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; @@ -54,7 +53,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -80,6 +78,7 @@ import android.view.View; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateDecelerateInterpolator; @@ -568,28 +567,6 @@ public final class Launcher extends Activity // When we resume Launcher, a different Activity might be responsible for the app // market intent, so refresh the icon updateAppMarketIcon(); - mAppsCustomizeTabHost.onResume(); - if (!mWorkspaceLoading) { - final ViewTreeObserver observer = mWorkspace.getViewTreeObserver(); - final Workspace workspace = mWorkspace; - // We want to let Launcher draw itself at least once before we force it to build - // layers on all the workspace pages, so that transitioning to Launcher from other - // apps is nice and speedy. Usually the first call to preDraw doesn't correspond to - // a true draw so we wait until the second preDraw call to be safe - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - boolean mFirstTime = true; - public boolean onPreDraw() { - if (mFirstTime) { - mFirstTime = false; - } else { - workspace.post(mBuildLayersRunnable); - observer.removeOnPreDrawListener(this); - } - return true; - } - }); - } - clearTypedText(); } @Override @@ -1067,6 +1044,33 @@ public final class Launcher extends Activity public void onWindowVisibilityChanged(int visibility) { mVisible = visibility == View.VISIBLE; updateRunning(); + // The following code used to be in onResume, but it turns out onResume is called when + // you're in All Apps and click home to go to the workspace. onWindowVisibilityChanged + // is a more appropriate event to handle + if (mVisible) { + mAppsCustomizeTabHost.onWindowVisible(); + if (!mWorkspaceLoading) { + final ViewTreeObserver observer = mWorkspace.getViewTreeObserver(); + final Workspace workspace = mWorkspace; + // We want to let Launcher draw itself at least once before we force it to build + // layers on all the workspace pages, so that transitioning to Launcher from other + // apps is nice and speedy. Usually the first call to preDraw doesn't correspond to + // a true draw so we wait until the second preDraw call to be safe + observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + boolean mFirstTime = true; + public boolean onPreDraw() { + if (mFirstTime) { + mFirstTime = false; + } else { + //workspace.post(mBuildLayersRunnable); + observer.removeOnPreDrawListener(this); + } + return true; + } + }); + } + clearTypedText(); + } } private void sendAdvanceMessage(long delay) { @@ -2218,7 +2222,8 @@ public final class Launcher extends Activity setPivotsForZoom(toView, scale); // Shrink workspaces away if going to AppsCustomize from workspace - mWorkspace.changeState(Workspace.State.SMALL, animated); + Animator workspaceAnim = + mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated); if (animated) { final ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration); @@ -2236,14 +2241,17 @@ public final class Launcher extends Activity alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f)); alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() { public void onAnimationUpdate(float a, float b) { - // don't need to invalidate because we do so above toView.setAlpha(a * 0f + b * 1f); } }); - alphaAnim.setStartDelay(startDelay); - alphaAnim.start(); - scaleAnim.addListener(new AnimatorListenerAdapter() { + // toView should appear right at the end of the workspace shrink + // animation + mStateAnimation = new AnimatorSet(); + mStateAnimation.play(alphaAnim).after(startDelay); + mStateAnimation.play(scaleAnim).after(startDelay); + + mStateAnimation.addListener(new AnimatorListenerAdapter() { boolean animationCancelled = false; @Override @@ -2283,19 +2291,43 @@ public final class Launcher extends Activity } }); - // toView should appear right at the end of the workspace shrink animation - mStateAnimation = new AnimatorSet(); - mStateAnimation.play(scaleAnim).after(startDelay); + if (workspaceAnim != null) { + mStateAnimation.play(workspaceAnim); + } boolean delayAnim = false; - if (toView instanceof LauncherTransitionable) { - LauncherTransitionable lt = (LauncherTransitionable) toView; - delayAnim = lt.onLauncherTransitionStart(instance, mStateAnimation, false); + LauncherTransitionable lt = (LauncherTransitionable) toView; + final ViewTreeObserver observer; + + lt.onLauncherTransitionStart(instance, mStateAnimation, false); + + // If any of the objects being animated haven't been measured/laid out + // yet, delay the animation until we get a layout pass + if ((lt.getContent().getMeasuredWidth() == 0) || + (mWorkspace.getMeasuredWidth() == 0) || + (toView.getMeasuredWidth() == 0)) { + observer = mWorkspace.getViewTreeObserver(); + delayAnim = true; + } else { + observer = null; } - // if the anim is delayed, the LauncherTransitionable is responsible for starting it - if (!delayAnim) { - // TODO: q-- what if this anim is cancelled before being started? or started after - // being cancelled? + + if (delayAnim) { + final OnGlobalLayoutListener delayedStart = new OnGlobalLayoutListener() { + public void onGlobalLayout() { + mWorkspace.post(new Runnable() { + public void run() { + // Need to update pivots for zoom if layout changed + setPivotsForZoom(toView, scale); + mStateAnimation.start(); + } + }); + observer.removeGlobalOnLayoutListener(this); + } + }; + observer.addOnGlobalLayoutListener(delayedStart); + } else { + setPivotsForZoom(toView, scale); mStateAnimation.start(); } } else { @@ -2324,7 +2356,8 @@ public final class Launcher extends Activity * This is the opposite of showAppsCustomizeHelper. * @param animated If true, the transition will be animated. */ - private void hideAppsCustomizeHelper(boolean animated, final boolean springLoaded) { + private void hideAppsCustomizeHelper( + State toState, boolean animated, final boolean springLoaded) { if (mStateAnimation != null) { mStateAnimation.cancel(); mStateAnimation = null; @@ -2336,6 +2369,16 @@ public final class Launcher extends Activity final float scaleFactor = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor); final View fromView = mAppsCustomizeTabHost; + Animator workspaceAnim = null; + + if (toState == State.WORKSPACE) { + int stagger = res.getInteger(R.integer.config_appsCustomizeWorkspaceAnimationStagger); + workspaceAnim = mWorkspace.getChangeStateAnimation( + Workspace.State.NORMAL, animated, stagger); + } else if (toState == State.APPS_CUSTOMIZE_SPRING_LOADED) { + workspaceAnim = mWorkspace.getChangeStateAnimation( + Workspace.State.SPRING_LOADED, animated); + } setPivotsForZoom(fromView, scaleFactor); updateWallpaperVisibility(true); @@ -2379,6 +2422,9 @@ public final class Launcher extends Activity mStateAnimation = new AnimatorSet(); mStateAnimation.playTogether(scaleAnim, alphaAnim); + if (workspaceAnim != null) { + mStateAnimation.play(workspaceAnim); + } mStateAnimation.start(); } else { fromView.setVisibility(View.GONE); @@ -2399,13 +2445,9 @@ public final class Launcher extends Activity } void showWorkspace(boolean animated) { - Resources res = getResources(); - int stagger = res.getInteger(R.integer.config_appsCustomizeWorkspaceAnimationStagger); - - mWorkspace.changeState(Workspace.State.NORMAL, animated, stagger); if (mState != State.WORKSPACE) { mWorkspace.setVisibility(View.VISIBLE); - hideAppsCustomizeHelper(animated, false); + hideAppsCustomizeHelper(State.WORKSPACE, animated, false); // Show the search bar and hotseat mSearchDropTargetBar.showSearchBar(animated); @@ -2454,8 +2496,7 @@ public final class Launcher extends Activity void enterSpringLoadedDragMode() { if (mState == State.APPS_CUSTOMIZE) { - mWorkspace.changeState(Workspace.State.SPRING_LOADED); - hideAppsCustomizeHelper(true, true); + hideAppsCustomizeHelper(State.APPS_CUSTOMIZE_SPRING_LOADED, true, true); hideDockDivider(); mState = State.APPS_CUSTOMIZE_SPRING_LOADED; } @@ -3327,7 +3368,7 @@ public final class Launcher extends Activity } interface LauncherTransitionable { - // return true if the callee will take care of start the animation by itself - boolean onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace); + View getContent(); + void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace); void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace); } diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 2db03da19..975686e49 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -1603,9 +1603,7 @@ public abstract class PagedView extends ViewGroup { // First, clear any pages that should no longer be loaded for (int i = 0; i < count; ++i) { Page layout = (Page) getPageAt(i); - if ((immediateAndOnly && i != page) || - (i < lowerPageBound) || - (i > upperPageBound)) { + if ((i < lowerPageBound) || (i > upperPageBound)) { if (layout.getPageChildCount() > 0) { layout.removeAllViewsOnPage(); } @@ -1617,7 +1615,6 @@ public abstract class PagedView extends ViewGroup { if ((i != page) && immediateAndOnly) { continue; } - Page layout = (Page) getPageAt(i); if (lowerPageBound <= i && i <= upperPageBound) { if (mDirtyPageContent.get(i)) { syncPageItems(i, (i == page) && immediateAndOnly); diff --git a/src/com/android/launcher2/PagedViewGridLayout.java b/src/com/android/launcher2/PagedViewGridLayout.java index b1b621598..90bfe88ec 100644 --- a/src/com/android/launcher2/PagedViewGridLayout.java +++ b/src/com/android/launcher2/PagedViewGridLayout.java @@ -109,6 +109,7 @@ public class PagedViewGridLayout extends GridLayout implements Page { @Override public void removeAllViewsOnPage() { removeAllViews(); + mOnLayoutListener = null; destroyHardwareLayer(); } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index fa3dfcbff..83408bae8 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -159,10 +159,7 @@ public class Workspace extends SmoothPagedView enum State { NORMAL, SPRING_LOADED, SMALL }; private State mState = State.NORMAL; private boolean mIsSwitchingState = false; - private boolean mSwitchStateAfterFirstLayout = false; - private State mStateAfterFirstLayout; - private AnimatorSet mAnimator; private AnimatorListener mChangeStateAnimationListener; boolean mAnimatingViewIntoPlace = false; @@ -405,7 +402,6 @@ public class Workspace extends SmoothPagedView public void onAnimationEnd(Animator animation) { mIsSwitchingState = false; mWallpaperOffset.setOverrideHorizontalCatchupConstant(false); - mAnimator = null; updateChildrenLayersEnabled(); } }; @@ -1249,19 +1245,6 @@ public class Workspace extends SmoothPagedView mUpdateWallpaperOffsetImmediately = true; } super.onLayout(changed, left, top, right, bottom); - - // if shrinkToBottom() is called on initialization, it has to be deferred - // until after the first call to onLayout so that it has the correct width - if (mSwitchStateAfterFirstLayout) { - mSwitchStateAfterFirstLayout = false; - // shrink can trigger a synchronous onLayout call, so we - // post this to avoid a stack overflow / tangled onLayout calls - post(new Runnable() { - public void run() { - changeState(mStateAfterFirstLayout, false); - } - }); - } } @Override @@ -1565,32 +1548,19 @@ public class Workspace extends SmoothPagedView mNewRotationYs = new float[childCount]; } - public void changeState(State shrinkState) { - changeState(shrinkState, true); - } - - void changeState(final State state, boolean animated) { - changeState(state, animated, 0); + Animator getChangeStateAnimation(final State state, boolean animated) { + return getChangeStateAnimation(state, animated, 0); } - void changeState(final State state, boolean animated, int delay) { + Animator getChangeStateAnimation(final State state, boolean animated, int delay) { if (mState == state) { - return; - } - if (mFirstLayout) { - // (mFirstLayout == "first layout has not happened yet") - // cancel any pending shrinks that were set earlier - mSwitchStateAfterFirstLayout = false; - mStateAfterFirstLayout = state; - return; + return null; } // Initialize animation arrays for the first time if necessary initAnimationArrays(); - // Cancel any running transition animations - if (mAnimator != null) mAnimator.cancel(); - mAnimator = new AnimatorSet(); + AnimatorSet anim = animated ? new AnimatorSet() : null; // Stop any scrolling, move to the current page right away setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage); @@ -1717,6 +1687,21 @@ public class Workspace extends SmoothPagedView } } }); + for (int i = 0; i < getChildCount(); i++) { + invalidate(); + if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) { + final CellLayout cl = (CellLayout) getChildAt(i); + cl.fastInvalidate(); + cl.setFastTranslationX(mNewTranslationXs[i]); + cl.setFastTranslationY(mNewTranslationYs[i]); + cl.setFastScaleX(mNewScaleXs[i]); + cl.setFastScaleY(mNewScaleYs[i]); + cl.setFastBackgroundAlpha(mNewBackgroundAlphas[i]); + cl.setBackgroundAlphaMultiplier(mNewBackgroundAlphaMultipliers[i]); + cl.setFastAlpha(mNewAlphas[i]); + } + } + animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() { public void onAnimationUpdate(float a, float b) { mTransitionProgress = b; @@ -1726,17 +1711,21 @@ public class Workspace extends SmoothPagedView } invalidate(); for (int i = 0; i < getChildCount(); i++) { - final CellLayout cl = (CellLayout) getChildAt(i); - cl.fastInvalidate(); - cl.setFastTranslationX(a * mOldTranslationXs[i] + b * mNewTranslationXs[i]); - cl.setFastTranslationY(a * mOldTranslationYs[i] + b * mNewTranslationYs[i]); - cl.setFastScaleX(a * mOldScaleXs[i] + b * mNewScaleXs[i]); - cl.setFastScaleY(a * mOldScaleYs[i] + b * mNewScaleYs[i]); - cl.setFastBackgroundAlpha( - a * mOldBackgroundAlphas[i] + b * mNewBackgroundAlphas[i]); - cl.setBackgroundAlphaMultiplier(a * mOldBackgroundAlphaMultipliers[i] + - b * mNewBackgroundAlphaMultipliers[i]); - cl.setFastAlpha(a * mOldAlphas[i] + b * mNewAlphas[i]); + if (mOldAlphas[i] != 0 || mNewAlphas[i] != 0) { + final CellLayout cl = (CellLayout) getChildAt(i); + cl.fastInvalidate(); + cl.setFastTranslationX( + a * mOldTranslationXs[i] + b * mNewTranslationXs[i]); + cl.setFastTranslationY( + a * mOldTranslationYs[i] + b * mNewTranslationYs[i]); + cl.setFastScaleX(a * mOldScaleXs[i] + b * mNewScaleXs[i]); + cl.setFastScaleY(a * mOldScaleYs[i] + b * mNewScaleYs[i]); + cl.setFastBackgroundAlpha( + a * mOldBackgroundAlphas[i] + b * mNewBackgroundAlphas[i]); + cl.setBackgroundAlphaMultiplier(a * mOldBackgroundAlphaMultipliers[i] + + b * mNewBackgroundAlphaMultipliers[i]); + cl.setFastAlpha(a * mOldAlphas[i] + b * mNewAlphas[i]); + } } syncChildrenLayersEnabledOnVisiblePages(); } @@ -1752,18 +1741,20 @@ public class Workspace extends SmoothPagedView return; } for (int i = 0; i < getChildCount(); i++) { - final CellLayout cl = (CellLayout) getChildAt(i); - cl.setFastRotationY(a * mOldRotationYs[i] + b * mNewRotationYs[i]); + if (mOldAlphas[i] != 0 || mNewAlphas[i] != 0 || + mOldRotationYs[i] != 0 || mNewRotationYs[i] != 0) { + final CellLayout cl = (CellLayout) getChildAt(i); + cl.setFastRotationY(a * mOldRotationYs[i] + b * mNewRotationYs[i]); + } } } }); - mAnimator.playTogether(animWithInterpolator, rotationAnim); - mAnimator.setStartDelay(delay); + anim.playTogether(animWithInterpolator, rotationAnim); + anim.setStartDelay(delay); // If we call this when we're not animated, onAnimationEnd is never called on // the listener; make sure we only use the listener when we're actually animating - mAnimator.addListener(mChangeStateAnimationListener); - mAnimator.start(); + anim.addListener(mChangeStateAnimationListener); } if (stateIsSpringLoaded) { @@ -1777,6 +1768,7 @@ public class Workspace extends SmoothPagedView animateBackgroundGradient(0f, true); } syncChildrenLayersEnabledOnVisiblePages(); + return anim; } /** |