OSDN Git Service

Fix for reveal animated drawables
authorAlan Viverette <alanv@google.com>
Wed, 19 Feb 2014 22:40:12 +0000 (14:40 -0800)
committerAlan Viverette <alanv@google.com>
Wed, 19 Feb 2014 22:40:12 +0000 (14:40 -0800)
Includes fixes for RevealDrawable clipping, touch feedback constant
state, and action bar background display lists.

BUG: 13065159
Change-Id: Ie4bf03f59da69047e18a8fe9233c3d24b0160576

core/java/com/android/internal/widget/ActionBarContainer.java
graphics/java/android/graphics/drawable/RevealDrawable.java
graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java

index 03fa9b4..c2d22dd 100644 (file)
@@ -19,6 +19,7 @@ package com.android.internal.widget;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.ColorFilter;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.ActionMode;
@@ -50,7 +51,8 @@ public class ActionBarContainer extends FrameLayout {
     public ActionBarContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        setBackgroundDrawable(null);
+        // Set a transparent background so that we project appropriately.
+        setBackground(new ActionBarBackgroundDrawable());
 
         TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.ActionBar);
@@ -242,24 +244,6 @@ public class ActionBarContainer extends FrameLayout {
     }
 
     @Override
-    public void onDraw(Canvas canvas) {
-        if (getWidth() == 0 || getHeight() == 0) {
-            return;
-        }
-
-        if (mIsSplit) {
-            if (mSplitBackground != null) mSplitBackground.draw(canvas);
-        } else {
-            if (mBackground != null) {
-                mBackground.draw(canvas);
-            }
-            if (mStackedBackground != null && mIsStacked) {
-                mStackedBackground.draw(canvas);
-            }
-        }
-    }
-
-    @Override
     public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
         // No starting an action mode for an action bar child! (Where would it go?)
         return null;
@@ -290,12 +274,13 @@ public class ActionBarContainer extends FrameLayout {
     public void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
 
-        final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
+        final View tabContainer = mTabContainer;
+        final boolean hasTabs = tabContainer != null && tabContainer.getVisibility() != GONE;
 
-        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
+        if (tabContainer != null && tabContainer.getVisibility() != GONE) {
             final int containerHeight = getMeasuredHeight();
-            final int tabHeight = mTabContainer.getMeasuredHeight();
-            mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
+            final int tabHeight = tabContainer.getMeasuredHeight();
+            tabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
         }
 
         boolean needsInvalidate = false;
@@ -306,13 +291,15 @@ public class ActionBarContainer extends FrameLayout {
             }
         } else {
             if (mBackground != null) {
-                mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
-                        mActionBarView.getRight(), mActionBarView.getBottom());
+                final ActionBarView actionBarView = mActionBarView;
+                mBackground.setBounds(actionBarView.getLeft(), actionBarView.getTop(),
+                        actionBarView.getRight(), actionBarView.getBottom());
                 needsInvalidate = true;
             }
-            if ((mIsStacked = hasTabs && mStackedBackground != null)) {
-                mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
-                        mTabContainer.getRight(), mTabContainer.getBottom());
+            mIsStacked = hasTabs;
+            if (hasTabs && mStackedBackground != null) {
+                mStackedBackground.setBounds(tabContainer.getLeft(), tabContainer.getTop(),
+                        tabContainer.getRight(), tabContainer.getBottom());
                 needsInvalidate = true;
             }
         }
@@ -321,4 +308,37 @@ public class ActionBarContainer extends FrameLayout {
             invalidate();
         }
     }
+
+    /**
+     * Dummy drawable so that we don't break background display lists and
+     * projection surfaces.
+     */
+    private class ActionBarBackgroundDrawable extends Drawable {
+        @Override
+        public void draw(Canvas canvas) {
+            if (mIsSplit) {
+                if (mSplitBackground != null) mSplitBackground.draw(canvas);
+            } else {
+                if (mBackground != null) {
+                    mBackground.draw(canvas);
+                }
+                if (mStackedBackground != null && mIsStacked) {
+                    mStackedBackground.draw(canvas);
+                }
+            }
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+    }
 }
index 38765e8..91de638 100644 (file)
@@ -18,7 +18,6 @@ package android.graphics.drawable;
 
 import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
@@ -233,16 +232,14 @@ public class RevealDrawable extends LayerDrawable {
 
         getDrawable(0).draw(canvas);
 
+        final Rect bounds = getBounds();
         final ArrayList<Ripple> activeRipples = mActiveRipples;
-        if (layerCount == 1 || activeRipples == null || activeRipples.isEmpty()) {
+        if (layerCount == 1 || bounds.isEmpty() || activeRipples == null
+                || activeRipples.isEmpty()) {
             // Nothing to reveal, we're done here.
             return;
         }
 
-        final Rect bounds = getBounds();
-        final int width = bounds.width();
-        final int height = bounds.height();
-
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
             mRipplePaint.setAntiAlias(true);
@@ -260,7 +257,11 @@ public class RevealDrawable extends LayerDrawable {
                 n--;
             } else {
                 if (layerSaveCount < 0) {
-                    layerSaveCount = canvas.saveLayer(0, 0, width, height, null, 0);
+                    layerSaveCount = canvas.saveLayer(
+                            bounds.left, bounds.top, bounds.right, bounds.bottom, null, 0);
+                    // Ripples must be clipped to bounds, otherwise SRC_IN will
+                    // miss them and we'll get artifacts.
+                    canvas.clipRect(bounds);
                 }
 
                 needsMask |= ripple.draw(canvas, mRipplePaint);
@@ -279,7 +280,8 @@ public class RevealDrawable extends LayerDrawable {
 
                 // TODO: When Drawable.setXfermode() is supported by all drawables,
                 // we won't need an extra layer.
-                canvas.saveLayer(0, 0, width, height, mMaskingPaint, 0);
+                canvas.saveLayer(
+                        bounds.left, bounds.top, bounds.right, bounds.bottom, mMaskingPaint, 0);
                 getDrawable(1).draw(canvas);
             }
 
index 1bfdc4d..f7cd9de 100644 (file)
@@ -338,11 +338,16 @@ public class TouchFeedbackDrawable extends Drawable {
         return dirtyBounds;
     }
 
-    private static class TouchFeedbackState extends ConstantState {
-        private ColorStateList mColorStateList;
-        private Xfermode mXfermode;
-        private int mTargetDensity;
-        private boolean mProjected;
+    @Override
+    public ConstantState getConstantState() {
+        return mState;
+    }
+
+    static class TouchFeedbackState extends ConstantState {
+        ColorStateList mColorStateList;
+        Xfermode mXfermode;
+        int mTargetDensity;
+        boolean mProjected;
 
         public TouchFeedbackState(TouchFeedbackState orig) {
             if (orig != null) {