Commit 7acc9abf authored by Xing Liu's avatar Xing Liu Committed by Commit Bot

Download Home V2: Fix an issue that thumbnails are scaled to 0.

Currently the AsyncImageView starts to retrieve thumbnails when the
view holders are binded before the actual layout happens, which results
in the width and height in thumbnail requests to be 0.

This CL delays the thumbnail request after the actual layout happens.

Also uses centerCrop for image and video view holders.

Bug: 890377
Change-Id: I98f3864027553614a40d8211ac72743e66929db5
Reviewed-on: https://chromium-review.googlesource.com/c/1255586
Commit-Queue: Xing Liu <xingliu@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595910}
parent 2d2da5d2
...@@ -35,7 +35,7 @@ public class ImageViewHolder extends ListItemViewHolder { ...@@ -35,7 +35,7 @@ public class ImageViewHolder extends ListItemViewHolder {
mThumbnail = itemView.findViewById(R.id.thumbnail); mThumbnail = itemView.findViewById(R.id.thumbnail);
} }
// ThumbnailAwareViewHolder implementation. // ListItemViewHolder implementation.
@Override @Override
public void bind(PropertyModel properties, ListItem item) { public void bind(PropertyModel properties, ListItem item) {
OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item; OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item;
......
...@@ -48,6 +48,7 @@ public class VideoViewHolder extends MoreButtonViewHolder { ...@@ -48,6 +48,7 @@ public class VideoViewHolder extends MoreButtonViewHolder {
mThumbnail = itemView.findViewById(R.id.thumbnail); mThumbnail = itemView.findViewById(R.id.thumbnail);
} }
// MoreButtonViewHolder implementation.
@Override @Override
public void bind(PropertyModel properties, ListItem item) { public void bind(PropertyModel properties, ListItem item) {
super.bind(properties, item); super.bind(properties, item);
......
...@@ -39,12 +39,10 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView { ...@@ -39,12 +39,10 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView {
private final Drawable mUnavailableDrawable; private final Drawable mUnavailableDrawable;
private final Drawable mWaitingDrawable; private final Drawable mWaitingDrawable;
/** private Factory mFactory;
* Used to handle synchronous responses to the callback in
* {@link #setAsyncImageDrawable(Factory)}.
*/
private boolean mWaitingForResponse;
private Runnable mCancelable; private Runnable mCancelable;
private boolean mWaitingForResponse;
/** Creates an {@link AsyncImageDrawable instance. */ /** Creates an {@link AsyncImageDrawable instance. */
public AsyncImageView(Context context) { public AsyncImageView(Context context) {
...@@ -81,10 +79,10 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView { ...@@ -81,10 +79,10 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView {
public void setAsyncImageDrawable(Factory factory) { public void setAsyncImageDrawable(Factory factory) {
// This will clear out any outstanding request. // This will clear out any outstanding request.
setImageDrawable(null); setImageDrawable(null);
setForegroundDrawableCompat(mWaitingDrawable); setForegroundDrawableCompat(mWaitingDrawable);
mCancelable = factory.get(this ::setAsyncImageDrawableResponse, getWidth(), getHeight());
if (!mWaitingForResponse) mCancelable = null; mFactory = factory;
retrieveDrawableIfNeeded();
} }
// RoundedCornerImageView implementation. // RoundedCornerImageView implementation.
...@@ -92,14 +90,18 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView { ...@@ -92,14 +90,18 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView {
public void setImageDrawable(Drawable drawable) { public void setImageDrawable(Drawable drawable) {
// If we had an outstanding async request, cancel it because we're now setting the drawable // If we had an outstanding async request, cancel it because we're now setting the drawable
// to something else. // to something else.
if (mWaitingForResponse) { cancelPreviousDrawableRequest();
if (mCancelable != null) mCancelable.run();
mCancelable = null;
mWaitingForResponse = false;
setForegroundDrawableCompat(null); setForegroundDrawableCompat(null);
super.setImageDrawable(drawable);
} }
super.setImageDrawable(drawable); // View implementation.
@Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
retrieveDrawableIfNeeded();
} }
private void setAsyncImageDrawableResponse(Drawable drawable) { private void setAsyncImageDrawableResponse(Drawable drawable) {
...@@ -108,4 +110,32 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView { ...@@ -108,4 +110,32 @@ public class AsyncImageView extends ForegroundRoundedCornerImageView {
setForegroundDrawableCompat(drawable == null ? mUnavailableDrawable : null); setForegroundDrawableCompat(drawable == null ? mUnavailableDrawable : null);
setImageDrawable(drawable); setImageDrawable(drawable);
} }
private void cancelPreviousDrawableRequest() {
mFactory = null;
if (mCancelable != null) {
mCancelable.run();
mCancelable = null;
mWaitingForResponse = false;
}
}
private void retrieveDrawableIfNeeded() {
// If width or height are not valid, don't start to retrieve the drawable since the
// thumbnail may be scaled down to 0.
if (getWidth() <= 0 || getHeight() <= 0) return;
if (mFactory != null) {
// Start to retrieve the drawable.
mWaitingForResponse = true;
mCancelable =
mFactory.get(this ::setAsyncImageDrawableResponse, getWidth(), getHeight());
// If setAsyncImageDrawableResponse is called synchronously, clear mCancelable.
if (!mWaitingForResponse) mCancelable = null;
mFactory = null;
}
}
} }
...@@ -155,31 +155,6 @@ public class RoundedCornerImageView extends ImageView { ...@@ -155,31 +155,6 @@ public class RoundedCornerImageView extends ImageView {
// Default to using the shader. // Default to using the shader.
mApplyShader = true; mApplyShader = true;
// If the scale type would not scale up the image, and the image is smaller than the
// view bounds, then just draw it normally so the shader won't have adverse effects.
// CENTER does not do any scaling, and simply centers the image. In that case we need to
// check to see if the image is smaller than the view in either dimension, and don't apply
// the shaer if it is. CENTER_INSIDE will only scale down, so we need to calculate the
// scaled size of the image, and only apply the shader if it happens to match the size of
// the view.
// TODO: this won't work with a custom image matrix, but that's probably ok for now
ScaleType scaleType = getScaleType();
if (scaleType == ScaleType.CENTER || scaleType == ScaleType.CENTER_INSIDE) {
int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft();
int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();
if (scaleType == ScaleType.CENTER_INSIDE) {
float scale = Math.min((float) viewWidth / (float) drawableWidth,
(float) viewHeight / (float) drawableHeight);
drawableWidth = (int) ((scale * drawableWidth) + 0.5f);
drawableHeight = (int) ((scale * drawableHeight) + 0.5f);
}
if ((drawableWidth < viewWidth) || (drawableHeight < viewHeight)) {
mApplyShader = false;
}
}
} }
@Override @Override
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment