OSDN Git Service

Widget size policy, size callbacks
authorAdam Cohen <adamcohen@google.com>
Fri, 2 Nov 2012 00:36:32 +0000 (17:36 -0700)
committerAdam Cohen <adamcohen@google.com>
Fri, 2 Nov 2012 06:32:55 +0000 (23:32 -0700)
-> vertically resizable widgets behave are sized to fill
-> non-vertically resizable widgets use the small size all the time
-> providing size call-backs. ensuring that we don't send excessive /
   incorrect size callbacks. These are expensive. Had to clean things
   up to ensure we only send the truth, and not bounce around.

Change-Id: I8038de01096906526e2622c6f1cd24c171e3a4ec

core/java/android/appwidget/AppWidgetHostView.java
policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java

index d56556f..be6a770 100644 (file)
@@ -244,14 +244,22 @@ public class AppWidgetHostView extends FrameLayout {
      *
      * @param newOptions The bundle of options, in addition to the size information,
      *          can be null.
-     * @param minWidth The minimum width that the widget will be displayed at.
-     * @param minHeight The maximum height that the widget will be displayed at.
-     * @param maxWidth The maximum width that the widget will be displayed at.
-     * @param maxHeight The maximum height that the widget will be displayed at.
+     * @param minWidth The minimum width in dips that the widget will be displayed at.
+     * @param minHeight The maximum height in dips that the widget will be displayed at.
+     * @param maxWidth The maximum width in dips that the widget will be displayed at.
+     * @param maxHeight The maximum height in dips that the widget will be displayed at.
      *
      */
     public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
             int maxHeight) {
+        updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight, false);
+    }
+
+    /**
+     * @hide
+     */
+    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
+            int maxHeight, boolean ignorePadding) {
         if (newOptions == null) {
             newOptions = new Bundle();
         }
@@ -265,10 +273,10 @@ public class AppWidgetHostView extends FrameLayout {
         int xPaddingDips = (int) ((padding.left + padding.right) / density);
         int yPaddingDips = (int) ((padding.top + padding.bottom) / density);
 
-        int newMinWidth = minWidth - xPaddingDips;
-        int newMinHeight = minHeight - yPaddingDips; 
-        int newMaxWidth = maxWidth - xPaddingDips;
-        int newMaxHeight = maxHeight - yPaddingDips;
+        int newMinWidth = minWidth - (ignorePadding ? 0 : xPaddingDips);
+        int newMinHeight = minHeight - (ignorePadding ? 0 : yPaddingDips);
+        int newMaxWidth = maxWidth - (ignorePadding ? 0 : xPaddingDips);
+        int newMaxHeight = maxHeight - (ignorePadding ? 0 : yPaddingDips);
 
         AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext);
 
index c89e880..a531558 100644 (file)
@@ -105,6 +105,10 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle
         // Reset the previous page size and ensure the current page is sized appropriately.
         // We only modify the page state if it is not currently under control by the slider.
         // This prevents conflicts.
+
+        // If the page hasn't switched, don't bother with any of this
+        if (mCurrentPage != newPageIndex) return;
+
         if (mPagedView != null && mChallengeLayout != null) {
             KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
             if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
index bb4272c..1474056 100644 (file)
@@ -63,7 +63,18 @@ public class KeyguardWidgetFrame extends FrameLayout {
     private float mBackgroundAlphaMultiplier = 1.0f;
     private Drawable mBackgroundDrawable;
     private Rect mBackgroundRect = new Rect();
+    private int mLastMeasuredWidth = -1;
+    private int mLastMeasuredHeight = 1;
+
+    // These variables are all needed in order to size things properly before we're actually
+    // measured.
     private int mSmallWidgetHeight;
+    private int mSmallFrameHeight;
+    private boolean mWidgetLockedSmall = false;
+    private int mMaxChallengeTop = -1;
+
+    // This will hold the width value before we've actually been measured
+    private int mFrameHeight;
 
     // Multiple callers may try and adjust the alpha of the frame. When a caller shows
     // the outlines, we give that caller control, and nobody else can fade them out.
@@ -99,10 +110,6 @@ public class KeyguardWidgetFrame extends FrameLayout {
         cancelLongPress();
     }
 
-    public void setMaxChallengeTop(int top) {
-        mSmallWidgetHeight = top - getPaddingTop();
-    }
-
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // Watch for longpress events at this level to make sure
@@ -263,22 +270,6 @@ public class KeyguardWidgetFrame extends FrameLayout {
     }
 
     /**
-     * Set the top location of the challenge.
-     *
-     * @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
-     *              is down.
-     */
-    private void setChallengeTop(int top, boolean updateWidgetSize) {
-        // The widget starts below the padding, and extends to the top of the challengs.
-        int widgetHeight = top - getPaddingTop();
-        int frameHeight = top + getPaddingBottom();
-        setFrameHeight(frameHeight);
-        if (updateWidgetSize) {
-            setWidgetHeight(widgetHeight);
-        }
-    }
-
-    /**
      * Depending on whether the security is up, the widget size needs to change
      * 
      * @param height The height of the widget, -1 for full height
@@ -298,28 +289,49 @@ public class KeyguardWidgetFrame extends FrameLayout {
         }
     }
 
+    public void setMaxChallengeTop(int top) {
+        boolean dirty = mMaxChallengeTop != top;
+        mSmallWidgetHeight = top - getPaddingTop();
+        mSmallFrameHeight = top + getPaddingBottom();
+        if (dirty && mIsSmall) {
+            setWidgetHeight(mSmallWidgetHeight);
+            setFrameHeight(mSmallFrameHeight);
+        } else if (dirty && mWidgetLockedSmall) {
+            setWidgetHeight(mSmallWidgetHeight);
+        }
+    }
+
     public boolean isSmall() {
         return mIsSmall;
     }
 
     public void adjustFrame(int challengeTop) {
-        setChallengeTop(challengeTop, false);
+        int frameHeight = challengeTop + getPaddingBottom();
+        setFrameHeight(frameHeight);
     }
 
     public void shrinkWidget() {
         mIsSmall = true;
-        setChallengeTop(mSmallWidgetHeight, true);
+        setWidgetHeight(mSmallWidgetHeight);
+        setFrameHeight(mSmallFrameHeight);
+    }
+
+    public void setWidgetLockedSmall(boolean locked) {
+        setWidgetHeight(mSmallWidgetHeight);
+        mWidgetLockedSmall = locked;
     }
 
     public void resetSize() {
         mIsSmall = false;
+        if (!mWidgetLockedSmall) {
+            setWidgetHeight(LayoutParams.MATCH_PARENT);
+        }
         setFrameHeight(getMeasuredHeight());
-        setWidgetHeight(LayoutParams.MATCH_PARENT);
     }
 
     public void setFrameHeight(int height) {
-        height = Math.min(height, getMeasuredHeight());
-        mBackgroundRect.set(0, 0, getMeasuredWidth(), height);
+        mFrameHeight = height;
+        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
         invalidate();
     }
 
@@ -359,10 +371,38 @@ public class KeyguardWidgetFrame extends FrameLayout {
                 mGradientColor, 0, Shader.TileMode.CLAMP);
         mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
                 mGradientColor, 0, Shader.TileMode.CLAMP);
-        mBackgroundRect.set(0, 0, w, h);
+
+        if (!mIsSmall) {
+            mFrameHeight = h;
+        }
+
+        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
         invalidate();
     }
 
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        performAppWidgetSizeCallbacksIfNecessary();
+    }
+
+    private void performAppWidgetSizeCallbacksIfNecessary() {
+        View content = getContent();
+        if (!(content instanceof AppWidgetHostView)) return;
+
+        boolean sizeDirty = content.getMeasuredWidth() != mLastMeasuredWidth ||
+                content.getMeasuredHeight() != mLastMeasuredHeight;
+        if (sizeDirty) {
+
+        }
+
+        AppWidgetHostView awhv = (AppWidgetHostView) content;
+        float density = getResources().getDisplayMetrics().density;
+
+        int width = (int) (content.getMeasuredWidth() / density);
+        int height = (int) (content.getMeasuredHeight() / density);
+        awhv.updateAppWidgetSize(null, width, height, width, height, true);
+    }
+
     void setOverScrollAmount(float r, boolean left) {
         if (Float.compare(mOverScrollAmount, r) != 0) {
             mOverScrollAmount = r;
index f04c4df..e3e7cd4 100644 (file)
@@ -21,6 +21,8 @@ import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Handler;
@@ -31,9 +33,9 @@ import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import com.android.internal.R;
@@ -250,10 +252,23 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
             FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                     LayoutParams.MATCH_PARENT);
             lp.gravity = Gravity.TOP;
+
             // The framework adds a default padding to AppWidgetHostView. We don't need this padding
             // for the Keyguard, so we override it to be 0.
             widget.setPadding(0,  0, 0, 0);
             frame.addView(widget, lp);
+
+            // We set whether or not this widget supports vertical resizing.
+            if (widget instanceof AppWidgetHostView) {
+                AppWidgetHostView awhv = (AppWidgetHostView) widget;
+                AppWidgetProviderInfo info = awhv.getAppWidgetInfo();
+                if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
+                    frame.setWidgetLockedSmall(false);
+                } else {
+                    // Lock the widget to be small.
+                    frame.setWidgetLockedSmall(true);
+                }
+            }
         } else {
             frame = (KeyguardWidgetFrame) widget;
         }
@@ -549,20 +564,20 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
             // coordinate relative to our children, hence we subtract the top padding.s
             maxChallengeTop = top - getPaddingTop();
             challengeShowing = scl.isChallengeShowing();
-        }
-
-        int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            KeyguardWidgetFrame frame = getWidgetPageAt(i);
-            frame.setMaxChallengeTop(maxChallengeTop);
 
-            // On the very first measure pass, if the challenge is showing, we need to make sure
-            // that the widget on the current page is small.
-            if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
-                frame.shrinkWidget();
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                KeyguardWidgetFrame frame = getWidgetPageAt(i);
+                frame.setMaxChallengeTop(maxChallengeTop);
+                // On the very first measure pass, if the challenge is showing, we need to make sure
+                // that the widget on the current page is small.
+                if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
+                    frame.shrinkWidget();
+                }
             }
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mHasMeasure = true;
     }
 
     void animateOutlinesAndSidePages(final boolean show) {