summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/launcher2/AppsCustomizeTabHost.java26
-rw-r--r--src/com/android/launcher2/Launcher.java139
-rw-r--r--src/com/android/launcher2/PagedView.java5
-rw-r--r--src/com/android/launcher2/PagedViewGridLayout.java1
-rw-r--r--src/com/android/launcher2/Workspace.java96
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;
}
/**