diff options
Diffstat (limited to 'src')
5 files changed, 114 insertions, 31 deletions
diff --git a/src/main/java/com/android/volley/toolbox/ImageLoader.java b/src/main/java/com/android/volley/toolbox/ImageLoader.java index 5348dc6..6dc86bb 100644 --- a/src/main/java/com/android/volley/toolbox/ImageLoader.java +++ b/src/main/java/com/android/volley/toolbox/ImageLoader.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap.Config; import android.os.Handler; import android.os.Looper; import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import com.android.volley.Request; import com.android.volley.RequestQueue; @@ -167,7 +168,7 @@ public class ImageLoader { * @param defaultImage Optional default image to return until the actual image is loaded. */ public ImageContainer get(String requestUrl, final ImageListener listener) { - return get(requestUrl, listener, 0, 0); + return get(requestUrl, listener, 0, 0, ScaleType.CENTER_INSIDE); } /** @@ -179,11 +180,13 @@ public class ImageLoader { * @param imageListener The listener to call when the remote image is loaded * @param maxWidth The maximum width of the returned image. * @param maxHeight The maximum height of the returned image. + * @param scaleType The ImageViews ScaleType used to calculate the needed image size. * @return A container object that contains all of the properties of the request, as well as * the currently available image (default if remote is not loaded). */ public ImageContainer get(String requestUrl, ImageListener imageListener, - int maxWidth, int maxHeight) { + int maxWidth, int maxHeight, ScaleType scaleType) { + // only fulfill requests that were initiated from the main thread. throwIfNotOnMainThread(); @@ -215,7 +218,8 @@ public class ImageLoader { // The request is not already in flight. Send the new request to the network and // track it. - Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, cacheKey); + Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType, + cacheKey); mRequestQueue.add(newRequest); mInFlightRequests.put(cacheKey, @@ -223,14 +227,14 @@ public class ImageLoader { return imageContainer; } - protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight, final String cacheKey) { + protected Request<Bitmap> makeImageRequest(String requestUrl, int maxWidth, int maxHeight, + ScaleType scaleType, final String cacheKey) { return new ImageRequest(requestUrl, new Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { onGetImageSuccess(cacheKey, response); } - }, maxWidth, maxHeight, - Config.RGB_565, new ErrorListener() { + }, maxWidth, maxHeight, scaleType, Config.RGB_565, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { onGetImageError(cacheKey, error); diff --git a/src/main/java/com/android/volley/toolbox/ImageRequest.java b/src/main/java/com/android/volley/toolbox/ImageRequest.java index 2ebe015..8a09ea1 100644 --- a/src/main/java/com/android/volley/toolbox/ImageRequest.java +++ b/src/main/java/com/android/volley/toolbox/ImageRequest.java @@ -26,6 +26,7 @@ import com.android.volley.VolleyLog; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; +import android.widget.ImageView.ScaleType; /** * A canned request for getting an image at a given URL and calling @@ -45,6 +46,7 @@ public class ImageRequest extends Request<Bitmap> { private final Config mDecodeConfig; private final int mMaxWidth; private final int mMaxHeight; + private ScaleType mScaleType; /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ private static final Object sDecodeLock = new Object(); @@ -63,18 +65,20 @@ public class ImageRequest extends Request<Bitmap> { * @param maxWidth Maximum width to decode this bitmap to, or zero for none * @param maxHeight Maximum height to decode this bitmap to, or zero for * none + * @param scaleType The ImageViews ScaleType used to calculate the needed image size. * @param decodeConfig Format to decode the bitmap to * @param errorListener Error listener, or null to ignore errors */ public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight, - Config decodeConfig, Response.ErrorListener errorListener) { - super(Method.GET, url, errorListener); + ScaleType scaleType, Config decodeConfig, Response.ErrorListener errorListener) { + super(Method.GET, url, errorListener); setRetryPolicy( new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); mListener = listener; mDecodeConfig = decodeConfig; mMaxWidth = maxWidth; mMaxHeight = maxHeight; + mScaleType = scaleType; } @Override @@ -92,14 +96,24 @@ public class ImageRequest extends Request<Bitmap> { * maintain aspect ratio with primary dimension * @param actualPrimary Actual size of the primary dimension * @param actualSecondary Actual size of the secondary dimension + * @param scaleType The ScaleType used to calculate the needed image size. */ private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, - int actualSecondary) { + int actualSecondary, ScaleType scaleType) { + // If no dominant value at all, just return the actual. - if (maxPrimary == 0 && maxSecondary == 0) { + if ((maxPrimary == 0) && (maxSecondary == 0)) { return actualPrimary; } + // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio. + if (scaleType == ScaleType.FIT_XY) { + if (maxPrimary == 0) { + return actualPrimary; + } + return maxPrimary; + } + // If primary is unspecified, scale primary to match secondary's scaling ratio. if (maxPrimary == 0) { double ratio = (double) maxSecondary / (double) actualSecondary; @@ -112,7 +126,16 @@ public class ImageRequest extends Request<Bitmap> { double ratio = (double) actualSecondary / (double) actualPrimary; int resized = maxPrimary; - if (resized * ratio > maxSecondary) { + + // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio. + if (scaleType == ScaleType.CENTER_CROP) { + if ((resized * ratio) < maxSecondary) { + resized = (int) (maxSecondary / ratio); + } + return resized; + } + + if ((resized * ratio) > maxSecondary) { resized = (int) (maxSecondary / ratio); } return resized; @@ -150,9 +173,9 @@ public class ImageRequest extends Request<Bitmap> { // Then compute the dimensions we would ideally like to decode to. int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, - actualWidth, actualHeight); + actualWidth, actualHeight, mScaleType); int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, - actualHeight, actualWidth); + actualHeight, actualWidth, mScaleType); // Decode to the nearest power of two scaling factor. decodeOptions.inJustDecodeBounds = false; diff --git a/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/src/main/java/com/android/volley/toolbox/NetworkImageView.java index 692e988..324dbc0 100644 --- a/src/main/java/com/android/volley/toolbox/NetworkImageView.java +++ b/src/main/java/com/android/volley/toolbox/NetworkImageView.java @@ -103,6 +103,7 @@ public class NetworkImageView extends ImageView { void loadImageIfNecessary(final boolean isInLayoutPass) { int width = getWidth(); int height = getHeight(); + ScaleType scaleType = getScaleType(); boolean wrapWidth = false, wrapHeight = false; if (getLayoutParams() != null) { @@ -177,7 +178,7 @@ public class NetworkImageView extends ImageView { setImageResource(mDefaultImageId); } } - }, maxWidth, maxHeight); + }, maxWidth, maxHeight, scaleType); // update the ImageContainer to be the new bitmap container. mImageContainer = newContainer; diff --git a/src/test/java/com/android/volley/toolbox/ImageRequestTest.java b/src/test/java/com/android/volley/toolbox/ImageRequestTest.java index 2f4495a..bd98e7d 100644 --- a/src/test/java/com/android/volley/toolbox/ImageRequestTest.java +++ b/src/test/java/com/android/volley/toolbox/ImageRequestTest.java @@ -18,7 +18,7 @@ package com.android.volley.toolbox; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; - +import android.widget.ImageView.ScaleType; import com.android.volley.NetworkResponse; import com.android.volley.Response; import org.junit.Test; @@ -47,30 +47,84 @@ public class ImageRequestTest { ShadowBitmapFactory.provideWidthAndHeightHints("fake", 1024, 500); NetworkResponse jpeg = new NetworkResponse(jpegBytes); - // No resize - verifyResize(jpeg, 0, 0, 1024, 500); + // Scale the image uniformly (maintain the image's aspect ratio) so that + // both dimensions (width and height) of the image will be equal to or + // less than the corresponding dimension of the view. + ScaleType scalteType = ScaleType.CENTER_INSIDE; // Exact sizes - verifyResize(jpeg, 512, 250, 512, 250); // exactly half - verifyResize(jpeg, 511, 249, 509, 249); // just under half - verifyResize(jpeg, 1080, 500, 1024, 500); // larger - verifyResize(jpeg, 500, 500, 500, 244); // keep same ratio + verifyResize(jpeg, 512, 250, scalteType, 512, 250); // exactly half + verifyResize(jpeg, 511, 249, scalteType, 509, 249); // just under half + verifyResize(jpeg, 1080, 500, scalteType, 1024, 500); // larger + verifyResize(jpeg, 500, 500, scalteType, 500, 244); // keep same ratio // Specify only width, preserve aspect ratio - verifyResize(jpeg, 512, 0, 512, 250); - verifyResize(jpeg, 800, 0, 800, 390); - verifyResize(jpeg, 1024, 0, 1024, 500); + verifyResize(jpeg, 512, 0, scalteType, 512, 250); + verifyResize(jpeg, 800, 0, scalteType, 800, 390); + verifyResize(jpeg, 1024, 0, scalteType, 1024, 500); // Specify only height, preserve aspect ratio - verifyResize(jpeg, 0, 250, 512, 250); - verifyResize(jpeg, 0, 391, 800, 391); - verifyResize(jpeg, 0, 500, 1024, 500); + verifyResize(jpeg, 0, 250, scalteType, 512, 250); + verifyResize(jpeg, 0, 391, scalteType, 800, 391); + verifyResize(jpeg, 0, 500, scalteType, 1024, 500); + + // No resize + verifyResize(jpeg, 0, 0, scalteType, 1024, 500); + + + // Scale the image uniformly (maintain the image's aspect ratio) so that + // both dimensions (width and height) of the image will be equal to or + // larger than the corresponding dimension of the view. + scalteType = ScaleType.CENTER_CROP; + + // Exact sizes + verifyResize(jpeg, 512, 250, scalteType, 512, 250); + verifyResize(jpeg, 511, 249, scalteType, 511, 249); + verifyResize(jpeg, 1080, 500, scalteType, 1024, 500); + verifyResize(jpeg, 500, 500, scalteType, 1024, 500); + + // Specify only width + verifyResize(jpeg, 512, 0, scalteType, 512, 250); + verifyResize(jpeg, 800, 0, scalteType, 800, 390); + verifyResize(jpeg, 1024, 0, scalteType, 1024, 500); + + // Specify only height + verifyResize(jpeg, 0, 250, scalteType, 512, 250); + verifyResize(jpeg, 0, 391, scalteType, 800, 391); + verifyResize(jpeg, 0, 500, scalteType, 1024, 500); + + // No resize + verifyResize(jpeg, 0, 0, scalteType, 1024, 500); + + + // Scale in X and Y independently, so that src matches dst exactly. This + // may change the aspect ratio of the src. + scalteType = ScaleType.FIT_XY; + + // Exact sizes + verifyResize(jpeg, 512, 250, scalteType, 512, 250); + verifyResize(jpeg, 511, 249, scalteType, 511, 249); + verifyResize(jpeg, 1080, 500, scalteType, 1024, 500); + verifyResize(jpeg, 500, 500, scalteType, 500, 500); + + // Specify only width + verifyResize(jpeg, 512, 0, scalteType, 512, 500); + verifyResize(jpeg, 800, 0, scalteType, 800, 500); + verifyResize(jpeg, 1024, 0, scalteType, 1024, 500); + + // Specify only height + verifyResize(jpeg, 0, 250, scalteType, 1024, 250); + verifyResize(jpeg, 0, 391, scalteType, 1024, 391); + verifyResize(jpeg, 0, 500, scalteType, 1024, 500); + + // No resize + verifyResize(jpeg, 0, 0, scalteType, 1024, 500); } private void verifyResize(NetworkResponse networkResponse, int maxWidth, int maxHeight, - int expectedWidth, int expectedHeight) { - ImageRequest request = new ImageRequest( - "", null, maxWidth, maxHeight, Config.RGB_565, null); + ScaleType scaleType, int expectedWidth, int expectedHeight) { + ImageRequest request = new ImageRequest("", null, maxWidth, maxHeight, scaleType, + Config.RGB_565, null); Response<Bitmap> response = request.parseNetworkResponse(networkResponse); assertNotNull(response); assertTrue(response.isSuccess()); diff --git a/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java b/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java index 48c81b6..bc2cc29 100644 --- a/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java +++ b/src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java @@ -1,6 +1,7 @@ package com.android.volley.toolbox; import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView.ScaleType; import org.junit.Before; import org.junit.Test; @@ -43,7 +44,7 @@ public class NetworkImageViewTest { public int lastMaxHeight; public ImageContainer get(String requestUrl, ImageListener imageListener, int maxWidth, - int maxHeight) { + int maxHeight, ScaleType scaleType) { lastRequestUrl = requestUrl; lastMaxWidth = maxWidth; lastMaxHeight = maxHeight; |