Delay loading All Apps pages until the first time we enter All Apps, making launcher startup faster (5000628)

Change-Id: I2a2218975141d7659184de83e505c7ab6e613232
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index af87653..1b01b48 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -18,9 +18,11 @@
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
     android:background="#FF000000">
     <LinearLayout
+        android:id="@+id/apps_customize_content"
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        android:visibility="gone">
         <!-- The layout_width of the tab bar gets overriden to align the content
              with the text in the tabs in AppsCustomizeTabHost. -->
         <FrameLayout
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index 41f8d7e..e79d41f 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 import android.widget.TabHost;
 import android.widget.TabWidget;
 import android.widget.TextView;
@@ -49,9 +50,11 @@
     private AppsCustomizePagedView mAppsCustomizePane;
     private boolean mSuppressContentCallback = false;
     private FrameLayout mAnimationBuffer;
+    private LinearLayout mContent;
 
     private boolean mInTransition;
     private boolean mResetAfterTransition;
+    private Animator mLauncherTransition;
 
     public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -93,6 +96,7 @@
         mTabsContainer = tabsContainer;
         mAppsCustomizePane = appsCustomizePane;
         mAnimationBuffer = (FrameLayout) findViewById(R.id.animation_buffer);
+        mContent = (LinearLayout) findViewById(R.id.apps_customize_content);
         if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
 
         // Configure the tabs content factory to return the same paged view (that we change the
@@ -313,21 +317,49 @@
         }
     }
 
-    /* LauncherTransitionable overrides */
-    @Override
-    public void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) {
-        mInTransition = true;
+    private void enableAndBuildHardwareLayer() {
         // isHardwareAccelerated() checks if we're attached to a window and if that
         // window is HW accelerated-- we were sometimes not attached to a window
         // and buildLayer was throwing an IllegalStateException
-        if (animation != null && isHardwareAccelerated()) {
+        if (isHardwareAccelerated()) {
             // Turn on hardware layers for performance
             setLayerType(LAYER_TYPE_HARDWARE, null);
 
-            // force building the layer at the beginning of the animation, so you don't get a
-            // blip early in the animation
+            // force building the layer, so you don't get a blip early in an animation
+            // when the layer is created layer
             buildLayer();
         }
+    }
+
+    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;
+        }
+    }
+
+    /* LauncherTransitionable overrides */
+    @Override
+    public boolean onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace) {
+        mInTransition = true;
+        boolean delayLauncherTransitionUntilLayout = false;
+        mLauncherTransition = null;
+
+        // if the content wasn't visible before, delay the launcher animation until after a cal
+        // to layout -- this prevents a blip
+        if (animation != null) {
+            if (mContent.getVisibility() == GONE) {
+                mLauncherTransition = animation;
+                delayLauncherTransitionUntilLayout = true;
+            }
+            mContent.setVisibility(VISIBLE);
+            if (!delayLauncherTransitionUntilLayout) {
+                enableAndBuildHardwareLayer();
+            }
+        }
+
         if (!toWorkspace && !LauncherApplication.isScreenLarge()) {
             mAppsCustomizePane.showScrollingIndicator(false);
         }
@@ -335,6 +367,7 @@
             mAppsCustomizePane.reset();
             mResetAfterTransition = false;
         }
+        return delayLauncherTransitionUntilLayout;
     }
 
     @Override
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index f91a471..7ee03fc 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2225,10 +2225,6 @@
             alphaAnim.setStartDelay(startDelay);
             alphaAnim.start();
 
-            if (toView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) toView).onLauncherTransitionStart(instance, scaleAnim,
-                        false);
-            }
             scaleAnim.addListener(new AnimatorListenerAdapter() {
                 boolean animationCancelled = false;
 
@@ -2272,7 +2268,18 @@
             // toView should appear right at the end of the workspace shrink animation
             mStateAnimation = new AnimatorSet();
             mStateAnimation.play(scaleAnim).after(startDelay);
-            mStateAnimation.start();
+
+            boolean delayAnim = false;
+            if (toView instanceof LauncherTransitionable) {
+                LauncherTransitionable lt = (LauncherTransitionable) toView;
+                delayAnim = lt.onLauncherTransitionStart(instance, mStateAnimation, false);
+            }
+            // 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?
+                mStateAnimation.start();
+            }
         } else {
             toView.setTranslationX(0.0f);
             toView.setTranslationY(0.0f);
@@ -3249,6 +3256,7 @@
 }
 
 interface LauncherTransitionable {
-    void onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace);
+    // return true if the callee will take care of start the animation by itself
+    boolean onLauncherTransitionStart(Launcher l, Animator animation, boolean toWorkspace);
     void onLauncherTransitionEnd(Launcher l, Animator animation, boolean toWorkspace);
 }