Dynamically determine size of customize tray.

Change-Id: I13235bbd01df8c31eb9bdfe88913db55624d8b9b
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index d308209..9d0c3ac 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -72,6 +72,8 @@
     private int mLastMeasureWidth = -1;
     private int mLastMeasureHeight = -1;
 
+    private int mMaxCellCountY;
+
     public AllAppsPagedView(Context context) {
         this(context, null);
     }
@@ -89,9 +91,10 @@
         a.recycle();
         setSoundEffectsEnabled(false);
 
-        Resources r = context.getResources();
+        final Resources r = context.getResources();
         setDragSlopeThreshold(
                 r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold) / 100.0f);
+        mMaxCellCountY = r.getInteger(R.integer.all_apps_view_maxCellCountY);
     }
 
     @Override
@@ -171,7 +174,19 @@
         availableHeight -= mPageLayoutPaddingTop + mPageLayoutPaddingBottom;
         availableHeight -= cellHeight; // Assume at least one row
         availableHeight -= screenHeight * 0.16f;
-        return (1 + availableHeight / (cellHeight + mPageLayoutHeightGap));
+        if (availableHeight > 0) {
+            return Math.min(mMaxCellCountY,
+                    1 + availableHeight / (cellHeight + mPageLayoutHeightGap));
+        }
+        return 0;
+    }
+
+    int getCellCountX() {
+        return mCellCountX;
+    }
+
+    int getCellCountY() {
+        return mCellCountY;
     }
 
     void allowHardwareLayerCreation() {
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 68ec535..5ac261f 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -108,6 +108,9 @@
     // The max number of wallpaper cells to take a "page" of wallpaper items
     private int mMaxWallpaperCellHSpan;
 
+    // The maximum number of rows in a paged view.
+    private int mMaxCellCountY;
+
     // The raw sources of data for each of the different tabs of the customization page
     private List<AppWidgetProviderInfo> mWidgetList;
     private List<ResolveInfo> mShortcutList;
@@ -143,7 +146,10 @@
 
     private int[] mDragViewOrigin = new int[2];
 
-    private int mPageContentWidth;
+    private int mPageContentWidth = -1;
+    private int mPageContentHeight = -1;
+
+    private AllAppsPagedView mAllAppsPagedView;
 
     public CustomizePagedView(Context context) {
         this(context, null, 0);
@@ -162,10 +168,6 @@
         mMaxWallpaperCellHSpan = a.getInt(R.styleable.CustomizePagedView_wallpaperCellCountX, 8);
         mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8);
         a.recycle();
-        a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
-        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 7);
-        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
-        a.recycle();
 
         mCustomizationType = CustomizationType.WidgetCustomization;
         mWidgetPages = new ArrayList<ArrayList<AppWidgetProviderInfo>>();
@@ -176,6 +178,8 @@
         setDragSlopeThreshold(
                 r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f);
 
+        mMaxCellCountY = r.getInteger(R.integer.customization_drawer_contents_maxCellCountY);
+
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
         setupWorkspaceLayout();
@@ -188,29 +192,44 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        // Base the size of this control on the size of the All Apps view.
+        final int cellCountX = mAllAppsPagedView.getCellCountX();
+        final int cellCountY = Math.min(mAllAppsPagedView.getCellCountY(), mMaxCellCountY);
 
-        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        if (cellCountX != mCellCountX || cellCountY != mCellCountY) {
+            mCellCountX = cellCountX;
+            mCellCountY = cellCountY;
 
-        if (mFirstMeasure) {
-            mFirstMeasure = false;
-
-            // TODO: actually calculate mCellCountX/mCellCountY as some function of
-            // widthSize and heightSize
-            //mCellCountX = ?
-            //mCellCountY = ?
-
-            // Since mCellCountX/mCellCountY changed, we need to update the pages
-            invalidatePageData();
-
-            // Create a dummy page and set it up to find out the content width (used by our parent)
+            // Create a dummy page and set it up to determine our size.
+            // The size is based on the app shortcuts tab having the same dimensions as All Apps.
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
             setupPage(layout);
             mPageContentWidth = layout.getContentWidth();
+            mPageContentHeight = layout.getContentHeight();
             mMinPageWidth = layout.getWidthBeforeFirstLayout();
         }
+        if (mPageContentHeight > 0) {
+            // Lock our height to the size of the page content
+            final int h = mPageContentHeight + mPageLayoutPaddingTop + mPageLayoutPaddingBottom;
+            heightSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
+        }
+        super.onMeasure(widthSpec, heightSpec);
+        mFirstMeasure = false;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mFirstLayout) {
+            invalidatePageData();
+
+            // invalidatePageData() is what causes the child pages to be created. We need the
+            // children to be measured before layout, so force a new measure here.
+            measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+        }
+        super.onLayout(changed, left, top, right, bottom);
+        mFirstLayout = false;
     }
 
     public void setLauncher(Launcher launcher) {
@@ -219,6 +238,10 @@
         mPackageManager = context.getPackageManager();
     }
 
+    public void setAllAppsPagedView(AllAppsPagedView view) {
+        mAllAppsPagedView = view;
+    }
+
     /**
      * Sets the list of applications that launcher has loaded.
      */
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
index ab50cf1..6306bda 100644
--- a/src/com/android/launcher2/CustomizeTrayTabHost.java
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -44,9 +44,14 @@
 
     private boolean mFirstLayout = true;
 
+    // How much of the vertical space this control should attempt to fill
+    private float mVerticalFillPercentage;
+
     private final LayoutInflater mInflater;
     private Context mContext;
 
+    private CustomizePagedView mCustomizePagedView;
+
     public CustomizeTrayTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
@@ -55,15 +60,17 @@
 
     @Override
     protected void onFinishInflate() {
+        final Resources res = getResources();
+
         setup();
 
-        final CustomizePagedView customizePagedView =
+        mCustomizePagedView =
             (CustomizePagedView) findViewById(R.id.customization_drawer_tab_contents);
 
         // Configure tabs
         TabContentFactory contentFactory = new TabContentFactory() {
             public View createTabContent(String tag) {
-                return customizePagedView;
+                return mCustomizePagedView;
             }
         };
 
@@ -87,26 +94,28 @@
         addTab(newTabSpec(SHORTCUTS_TAG)
                 .setIndicator(tabView).setContent(contentFactory));
 
+        mVerticalFillPercentage =
+                res.getInteger(R.integer.customization_drawer_verticalFillPercentage) / 100f;
+
         setOnTabChangedListener(new OnTabChangeListener() {
             public void onTabChanged(String tabId) {
                 final CustomizePagedView.CustomizationType newType =
                     getCustomizeFilterForTabTag(tabId);
-                if (newType != customizePagedView.getCustomizationFilter()) {
+                if (newType != mCustomizePagedView.getCustomizationFilter()) {
                     // animate the changing of the tab content by fading pages in and out
-                    final Resources res = getResources();
                     final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
-                    final float alpha = customizePagedView.getAlpha();
-                    ValueAnimator alphaAnim = ObjectAnimator.ofFloat(customizePagedView,
+                    final float alpha = mCustomizePagedView.getAlpha();
+                    ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
                             "alpha", alpha, 0.0f);
                     alphaAnim.setDuration(duration);
                     alphaAnim.addListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationEnd(Animator animation) {
-                            customizePagedView.setCustomizationFilter(newType);
+                            mCustomizePagedView.setCustomizationFilter(newType);
 
-                            final float alpha = customizePagedView.getAlpha();
+                            final float alpha = mCustomizePagedView.getAlpha();
                             ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
-                                    customizePagedView, "alpha", alpha, 1.0f);
+                                    mCustomizePagedView, "alpha", alpha, 1.0f);
                             alphaAnim.setDuration(duration);
                             alphaAnim.start();
                         }
@@ -138,6 +147,22 @@
     }
 
     @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        // If there's extra room, try to grow to fill it
+        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+            final int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
+            final int finalHeight = Math.max(getMeasuredHeight(),
+                        (int) (availableHeight * mVerticalFillPercentage));
+
+            // Measure a second time with EXACTLY so that we get sized correctly
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(finalHeight, MeasureSpec.EXACTLY);
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         if (mFirstLayout) {
             mFirstLayout = false;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 4569eac..2a16e99 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -933,6 +933,7 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.setLauncher(this);
             mCustomizePagedView.setDragController(dragController);
+            mCustomizePagedView.setAllAppsPagedView(mAllAppsPagedView);
         } else {
              ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
              hotseatLeft.setContentDescription(mHotseatLabels[0]);
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index 15b155f..0ae7a59 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -286,11 +286,17 @@
     }
 
     int getContentHeight() {
-        return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+        if (mCellCountY > 0) {
+            return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+        }
+        return 0;
     }
 
     int getWidthBeforeFirstLayout() {
-        return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+        if (mCellCountX > 0) {
+            return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+        }
+        return 0;
     }
 
     @Override