diff options
5 files changed, 43 insertions, 37 deletions
diff --git a/src/com/android/bitmap/RequestKey.java b/src/com/android/bitmap/RequestKey.java index 882c75b..933f61f 100644 --- a/src/com/android/bitmap/RequestKey.java +++ b/src/com/android/bitmap/RequestKey.java @@ -67,8 +67,10 @@ public interface RequestKey { /** * Create an {@link FileDescriptorFactory} for a local file stored on the device and pass it to - * the given callback. This method will be called first; if it returns null, - * {@link #createInputStream()} will be called. + * the given callback. This method will be called in favor of {@link #createInputStream()}}, + * which will only be called if null is returned from this method, + * or {@link Callback#fileDescriptorFactoryCreated(RequestKey, FileDescriptorFactory)} is called + * with a null FileDescriptorFactory. * * Clients should implement this method if files are in the local cache folder, or if files must * be downloaded and cached. @@ -77,8 +79,9 @@ public interface RequestKey { * * @param key The key to create a FileDescriptorFactory for. This key will be passed to the * callback so it can check whether the key has changed. - * @param callback The callback to notify once the FileDescriptorFactory has been created. Do - * not invoke the callback directly from this method. Instead, create a handler + * @param callback The callback to notify once the FileDescriptorFactory is created or has failed + * to be created. + * Do not invoke the callback directly from this method. Instead, create a handler * and post a Runnable. * * @return If the client will attempt to create a FileDescriptorFactory, return a Cancelable @@ -136,4 +139,4 @@ public interface RequestKey { */ void cancel(); } -}
\ No newline at end of file +} diff --git a/src/com/android/bitmap/drawable/BasicBitmapDrawable.java b/src/com/android/bitmap/drawable/BasicBitmapDrawable.java index 3ecc15b..67884df 100644 --- a/src/com/android/bitmap/drawable/BasicBitmapDrawable.java +++ b/src/com/android/bitmap/drawable/BasicBitmapDrawable.java @@ -58,8 +58,6 @@ import java.util.concurrent.TimeUnit; public class BasicBitmapDrawable extends Drawable implements DecodeCallback, Drawable.Callback, RequestKey.Callback { - protected static Rect sRect; - protected RequestKey mCurrKey; protected RequestKey mPrevKey; protected int mDecodeWidth; @@ -67,6 +65,7 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, protected final Paint mPaint = new Paint(); private final BitmapCache mCache; + private final Rect mRect = new Rect(); private final boolean mLimitDensity; private final float mDensity; @@ -100,10 +99,6 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, mPaint.setFilterBitmap(true); mPaint.setAntiAlias(true); mPaint.setDither(true); - - if (sRect == null) { - sRect = new Rect(); - } } public final RequestKey getKey() { @@ -265,12 +260,6 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, } mCreateFileDescriptorFactoryTask = null; - if (factory == null) { - // Failed. - onDecodeFailed(); - return; - } - if (key.equals(mCurrKey)) { decode(factory); } @@ -359,7 +348,7 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, bounds.width(), bounds.height(), bounds.height(), Integer.MAX_VALUE, getDecodeHorizontalCenter(), getDrawVerticalCenter(), false /* absoluteFraction */, - getDrawVerticalOffsetMultiplier(), sRect); + getDrawVerticalOffsetMultiplier(), mRect); final int orientation = mBitmap.getOrientation(); // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has @@ -367,7 +356,7 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, // coordinates. RectUtils.rotateRectForOrientation(orientation, new Rect(0, 0, mBitmap.getLogicalWidth(), mBitmap.getLogicalHeight()), - sRect); + mRect); // We may need to rotate the canvas, so we also have to rotate the bounds. final Rect rotatedBounds = new Rect(bounds); @@ -376,7 +365,7 @@ public class BasicBitmapDrawable extends Drawable implements DecodeCallback, // Rotate the canvas. canvas.save(); canvas.rotate(orientation, bounds.centerX(), bounds.centerY()); - onDrawBitmap(canvas, sRect, rotatedBounds); + onDrawBitmap(canvas, mRect, rotatedBounds); canvas.restore(); } } diff --git a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java index cb8ede7..dec8acf 100644 --- a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java +++ b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java @@ -37,10 +37,10 @@ import com.android.bitmap.BitmapCache; * This draws all bitmaps as a circle with an optional border stroke. */ public class CircularBitmapDrawable extends ExtendedBitmapDrawable { - private static Matrix sMatrix = new Matrix(); - private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); + private final Rect mRect = new Rect(); + private final Matrix mMatrix = new Matrix(); private float mBorderWidth; private Bitmap mShaderBitmap; @@ -104,8 +104,8 @@ public class CircularBitmapDrawable extends ExtendedBitmapDrawable { (BitmapDrawable) drawable.getInnerDrawable(); Bitmap bitmap = placeholder.getBitmap(); float alpha = placeholder.getPaint().getAlpha() / 255f; - sRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); - onDrawCircularBitmap(bitmap, canvas, sRect, bounds, alpha); + mRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); + onDrawCircularBitmap(bitmap, canvas, mRect, bounds, alpha); } else { super.onDrawPlaceholderOrProgress(canvas, drawable); } @@ -137,14 +137,14 @@ public class CircularBitmapDrawable extends ExtendedBitmapDrawable { mShaderBitmap = bitmap; } - sMatrix.reset(); + mMatrix.reset(); // Fit bitmap to bounds. float scale = Math.max((float) dst.width() / src.width(), (float) dst.height() / src.height()); - sMatrix.postScale(scale, scale); + mMatrix.postScale(scale, scale); // Translate bitmap to dst bounds. - sMatrix.postTranslate(dst.left, dst.top); - shader.setLocalMatrix(sMatrix); + mMatrix.postTranslate(dst.left, dst.top); + shader.setLocalMatrix(mMatrix); mBitmapPaint.setShader(shader); int oldAlpha = mBitmapPaint.getAlpha(); diff --git a/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java b/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java index fc54419..2fcc412 100644 --- a/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java +++ b/src/com/android/bitmap/drawable/ExtendedBitmapDrawable.java @@ -712,11 +712,8 @@ public class ExtendedBitmapDrawable extends BasicBitmapDrawable implements * This should not be confused with {@link #setParallaxFraction(float)}. This field * determines the general section for decode. The parallax fraction then determines the * slice from within that section for display. - * - * The default value of 1f / 3 provides a good heuristic for the subject's face in a - * portrait photo. */ - public float decodeVerticalCenter = 1f / 3; + public float decodeVerticalCenter = 1f / 2; /** * Required field if {@link #FEATURE_ORDERED_DISPLAY} is supported. diff --git a/src/com/android/bitmap/view/BitmapDrawableImageView.java b/src/com/android/bitmap/view/BitmapDrawableImageView.java index 9a88f3f..5cbc58d 100644 --- a/src/com/android/bitmap/view/BitmapDrawableImageView.java +++ b/src/com/android/bitmap/view/BitmapDrawableImageView.java @@ -30,6 +30,11 @@ import com.android.bitmap.drawable.BasicBitmapDrawable; * A helpful ImageView replacement that can generally be used in lieu of ImageView. * BitmapDrawableImageView has logic to unbind its BasicBitmapDrawable when it is detached from the * window. + * + * If you are using this with RecyclerView, + * or any use-case where {@link android.view.View#onDetachedFromWindow} is + * not a good signal for unbind, + * makes sure you {@link #setShouldUnbindOnDetachFromWindow} to false. */ public class BitmapDrawableImageView extends ImageView { private static final boolean HAS_TRANSIENT_STATE_SUPPORTED = @@ -38,6 +43,7 @@ public class BitmapDrawableImageView extends ImageView { private static final boolean PERMANENT = !TEMPORARY; private BasicBitmapDrawable mDrawable; + private boolean mShouldUnbindOnDetachFromWindow = true; private boolean mAttachedToWindow; public BitmapDrawableImageView(final Context context) { @@ -53,6 +59,14 @@ public class BitmapDrawableImageView extends ImageView { super(context, attrs, defStyle); } + public boolean shouldUnbindOnDetachFromWindow() { + return mShouldUnbindOnDetachFromWindow; + } + + public void setShouldUnbindOnDetachFromWindow(boolean shouldUnbindOnDetachFromWindow) { + mShouldUnbindOnDetachFromWindow = shouldUnbindOnDetachFromWindow; + } + /** * Get the source drawable for this BitmapDrawableImageView. * @return The source drawable casted to the given type, or null if the type does not match. @@ -72,11 +86,13 @@ public class BitmapDrawableImageView extends ImageView { */ public <E extends BasicBitmapDrawable> void setTypedDrawable(E drawable) { super.setImageDrawable(drawable); - unbindDrawable(); + if (drawable != mDrawable) { + unbindDrawable(); + } mDrawable = drawable; } - private void unbindDrawable() { + public void unbindDrawable() { unbindDrawable(PERMANENT); } @@ -119,7 +135,7 @@ public class BitmapDrawableImageView extends ImageView { super.onAttachedToWindow(); mAttachedToWindow = true; if (mDrawable != null && mDrawable.getKey() == null - && mDrawable.getPreviousKey() != null) { + && mDrawable.getPreviousKey() != null && mShouldUnbindOnDetachFromWindow) { mDrawable.bind(mDrawable.getPreviousKey()); } } @@ -128,7 +144,8 @@ public class BitmapDrawableImageView extends ImageView { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mAttachedToWindow = false; - if (HAS_TRANSIENT_STATE_SUPPORTED && !hasTransientState()) { + if (HAS_TRANSIENT_STATE_SUPPORTED && !hasTransientState() + && mShouldUnbindOnDetachFromWindow) { unbindDrawable(TEMPORARY); } } @@ -136,7 +153,7 @@ public class BitmapDrawableImageView extends ImageView { @Override public void setHasTransientState(boolean hasTransientState) { super.setHasTransientState(hasTransientState); - if (!hasTransientState && !mAttachedToWindow) { + if (!hasTransientState && !mAttachedToWindow && mShouldUnbindOnDetachFromWindow) { unbindDrawable(TEMPORARY); } } |