Merge "NumberPicker does not not fit on Crespo in landscape." into ics-mr1
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index cf015c4..320c650 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -203,6 +203,16 @@
     private final EditText mInputText;
 
     /**
+     * The max height of this widget.
+     */
+    private final int mMaxHeight;
+
+    /**
+     * The max width of this widget.
+     */
+    private final int mMaxWidth;
+
+    /**
      * The height of the text.
      */
     private final int mTextSize;
@@ -517,6 +527,8 @@
                 getResources().getDisplayMetrics());
         mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
                 R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
+        mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight, 0);
+        mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth, 0);
         attributesArray.recycle();
 
         mShowInputControlsAnimimationDuration = getResources().getInteger(
@@ -665,7 +677,38 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
+        if (mMaxHeight <= 0 && mMaxWidth <= 0) {
+            super.onLayout(changed, left, top, right, bottom);
+        } else {
+            final int msrdWdth = getMeasuredWidth();
+            final int msrdHght = getMeasuredHeight();
+
+            // Increment button at the top.
+            final int inctBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
+            final int incrBtnLeft = (msrdWdth - inctBtnMsrdWdth) / 2;
+            final int incrBtnTop = 0;
+            final int incrBtnRight = incrBtnLeft + inctBtnMsrdWdth;
+            final int incrBtnBottom = incrBtnTop + mIncrementButton.getMeasuredHeight();
+            mIncrementButton.layout(incrBtnLeft, incrBtnTop, incrBtnRight, incrBtnBottom);
+
+            // Input text centered horizontally.
+            final int inptTxtMsrdWdth = mInputText.getMeasuredWidth();
+            final int inptTxtMsrdHght = mInputText.getMeasuredHeight();
+            final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2;
+            final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2;
+            final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth;
+            final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght;
+            mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom);
+
+            // Decrement button at the top.
+            final int decrBtnMsrdWdth = mIncrementButton.getMeasuredWidth();
+            final int decrBtnLeft = (msrdWdth - decrBtnMsrdWdth) / 2;
+            final int decrBtnTop = msrdHght - mDecrementButton.getMeasuredHeight();
+            final int decrBtnRight = decrBtnLeft + decrBtnMsrdWdth;
+            final int decrBtnBottom = msrdHght;
+            mDecrementButton.layout(decrBtnLeft, decrBtnTop, decrBtnRight, decrBtnBottom);
+        }
+
         if (!mScrollWheelAndFadingEdgesInitialized) {
             mScrollWheelAndFadingEdgesInitialized = true;
             // need to do all this when we know our size
@@ -675,6 +718,24 @@
     }
 
     @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        final int measuredWidth;
+        if (mMaxWidth > 0) {
+            measuredWidth = getMaxSize(widthMeasureSpec, mMaxWidth);
+        } else {
+            measuredWidth = getMeasuredWidth();
+        }
+        final int measuredHeight;
+        if (mMaxHeight > 0) {
+            measuredHeight = getMaxSize(heightMeasureSpec, mMaxHeight);
+        } else {
+            measuredHeight = getMeasuredHeight();
+        }
+        setMeasuredDimension(measuredWidth, measuredHeight);
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         if (!isEnabled() || !mFlingable) {
             return false;
@@ -700,17 +761,14 @@
                     hideInputControls();
                     return true;
                 }
-                if (isEventInViewHitRect(event, mInputText)
-                        || (!mIncrementButton.isShown()
-                                && isEventInViewHitRect(event, mIncrementButton))
-                        || (!mDecrementButton.isShown()
-                                && isEventInViewHitRect(event, mDecrementButton))) {
-                    mAdjustScrollerOnUpEvent = false;
-                    setSelectorWheelState(SELECTOR_WHEEL_STATE_LARGE);
-                    hideInputControls();
-                    return true;
+                if (isEventInVisibleViewHitRect(event, mIncrementButton)
+                        || isEventInVisibleViewHitRect(event, mDecrementButton)) {
+                    return false;
                 }
-                break;
+                mAdjustScrollerOnUpEvent = false;
+                setSelectorWheelState(SELECTOR_WHEEL_STATE_LARGE);
+                hideInputControls();
+                return true;
             case MotionEvent.ACTION_MOVE:
                 float currentMoveY = event.getY();
                 int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
@@ -1240,6 +1298,28 @@
     }
 
     /**
+     * Gets the max value for a size based on the measure spec passed by
+     * the parent and the max value for that size.
+     *
+     * @param measureSpec The measure spec.
+     * @param maxValue The max value for the size.
+     * @return The max size.
+     */
+    private int getMaxSize(int measureSpec, int maxValue) {
+        final int mode = MeasureSpec.getMode(measureSpec);
+        switch (mode) {
+            case MeasureSpec.EXACTLY:
+                return MeasureSpec.getSize(measureSpec);
+            case MeasureSpec.AT_MOST:
+                return Math.min(MeasureSpec.getSize(measureSpec), maxValue);
+            case MeasureSpec.UNSPECIFIED:
+                return maxValue;
+            default:
+                throw new IllegalArgumentException();
+        }
+    }
+
+    /**
      * Resets the selector indices and clear the cached
      * string representation of these indices.
      */
@@ -1335,11 +1415,14 @@
     }
 
     /**
-     * @return If the <code>event</code> is in the <code>view</code>.
+     * @return If the <code>event</code> is in the visible <code>view</code>.
      */
-    private boolean isEventInViewHitRect(MotionEvent event, View view) {
-        view.getHitRect(mTempRect);
-        return mTempRect.contains((int) event.getX(), (int) event.getY());
+    private boolean isEventInVisibleViewHitRect(MotionEvent event, View view) {
+        if (view.getVisibility() == VISIBLE) {
+            view.getHitRect(mTempRect);
+            return mTempRect.contains((int) event.getX(), (int) event.getY());
+        }
+        return false;
     }
 
     /**
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d7691f7..65e11b4 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3572,6 +3572,10 @@
         <attr name="selectionDivider" format="reference" />
         <!-- @hide The height of the selection divider. -->
         <attr name="selectionDividerHeight" format="dimension" />
+        <!-- @hide The max height of the NumberPicker. -->
+        <attr name="maxHeight" />
+        <!-- @hide The max width of the NumberPicker. -->
+        <attr name="maxWidth" />
     </declare-styleable>
 
     <declare-styleable name="TimePicker">
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e60e8b2..a4bdf23 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1646,6 +1646,8 @@
         <item name="android:flingable">true</item>
         <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
         <item name="android:selectionDividerHeight">2dip</item>
+        <item name="android:maxHeight">180dip</item>
+        <item name="android:maxWidth">56dip</item>
     </style>
 
     <style name="Widget.Holo.TimePicker" parent="Widget.TimePicker">
@@ -1661,13 +1663,13 @@
         <item name="android:background">@null</item>
         <item name="android:src">@android:drawable/numberpicker_up_btn_holo_dark</item>
         <item name="android:paddingTop">16dip</item>
-        <item name="android:paddingBottom">36dip</item>
+        <item name="android:paddingBottom">22dip</item>
     </style>
 
     <style name="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@null</item>
         <item name="android:src">@android:drawable/numberpicker_down_btn_holo_dark</item>
-        <item name="android:paddingTop">36dip</item>
+        <item name="android:paddingTop">22dip</item>
         <item name="android:paddingBottom">16dip</item>
     </style>