Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java |
| index d76bd1c590f129ab676224a86e9a04d31f852eb1..7922b30ded8793b64fc9c4c221b8d5a78f1b57c3 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java |
| @@ -4,6 +4,14 @@ |
| package org.chromium.chrome.browser.ntp.snippets; |
| +import android.content.res.Resources; |
| +import android.graphics.Bitmap; |
| +import android.graphics.BitmapFactory; |
| +import android.graphics.drawable.BitmapDrawable; |
| +import android.graphics.drawable.Drawable; |
| +import android.graphics.drawable.TransitionDrawable; |
| +import android.media.ThumbnailUtils; |
| +import android.os.AsyncTask; |
| import android.text.format.DateUtils; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| @@ -11,6 +19,7 @@ |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| +import org.chromium.base.Log; |
| import org.chromium.base.metrics.RecordHistogram; |
| import org.chromium.base.metrics.RecordUserAction; |
| import org.chromium.chrome.R; |
| @@ -19,11 +28,18 @@ |
| import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem; |
| import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder; |
| +import java.io.IOException; |
| +import java.io.InputStream; |
| +import java.net.URL; |
| + |
| /** |
| * A class that represents the view for a single card snippet. |
| */ |
| public class SnippetArticleViewHolder extends NewTabPageViewHolder implements View.OnClickListener { |
| + private static final String TAG = "NtpSnippets"; |
| + private static final int FADE_IN_ANIMATION_TIME_MS = 300; |
| private final NewTabPageManager mNewTabPageManager; |
| + private AsyncTask<String, Void, Bitmap> mThumbnailFetchingTask; |
| public TextView mHeadlineTextView; |
| public TextView mPublisherTextView; |
| public TextView mArticleSnippetTextView; |
| @@ -90,7 +106,68 @@ public void onBindViewHolder(NewTabPageListItem article) { |
| mUrl = item.mUrl; |
| mPosition = item.mPosition; |
| - item.setThumbnailOnView(mThumbnailView); |
| + updateThumbnail(item); |
| + } |
| + |
| + private void updateThumbnail(final SnippetArticle snippet) { |
| + // If this view has a pending fetching task, it will display the stale thumbnail when it |
| + // finishes, so we need to cancel that task. |
| + if (mThumbnailFetchingTask != null) mThumbnailFetchingTask.cancel(true); |
| + |
| + if (snippet.getThumbnailBitmap() != null) { |
| + mThumbnailView.setImageBitmap(snippet.getThumbnailBitmap()); |
|
Bernhard Bauer
2016/04/12 11:21:19
Return in this case?
dgn
2016/04/12 13:40:21
Done.
|
| + } else { |
| + mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder); |
| + mThumbnailFetchingTask = new AsyncTask<String, Void, Bitmap>() { |
| + |
| + @Override |
| + protected Bitmap doInBackground(String... params) { |
| + String bitmapUrl = params[0]; |
| + if (bitmapUrl.isEmpty()) { |
| + Log.e(TAG, "Could not get image thumbnail due to empty URL"); |
|
Bernhard Bauer
2016/04/12 11:21:19
Move this out of the task?
dgn
2016/04/12 13:40:21
Done.
|
| + return null; |
| + } |
| + |
| + try (InputStream is = new URL(bitmapUrl).openStream()) { |
| + return BitmapFactory.decodeStream(is); |
| + } catch (IOException e) { |
| + Log.e(TAG, "Could not get image thumbnail", e); |
| + } |
| + |
| + return null; |
| + } |
| + |
| + @Override |
| + protected void onPostExecute(Bitmap result) { |
| + fadeThumbnailIn(snippet, result); |
|
Bernhard Bauer
2016/04/12 11:21:19
Skip this if the result is null?
dgn
2016/04/12 13:40:21
Done.
|
| + } |
| + }; |
| + |
| + mThumbnailFetchingTask.executeOnExecutor( |
| + AsyncTask.THREAD_POOL_EXECUTOR, snippet.mThumbnailUrl); |
| + } |
| + } |
| + |
| + private void fadeThumbnailIn(SnippetArticle snippet, Bitmap thumbnail) { |
| + if (thumbnail == null) return; // Nothing to do, we keep the placeholder. |
| + |
| + // We need to crop and scale the downloaded bitmap, as the ImageView we set it on won't be |
| + // able to do so when using a TransitionDrawable (as opposed to the straight bitmap). |
| + // That's a limitation of TransitionDrawable, which doesn't handle layers of varying sizes. |
| + Resources res = mThumbnailView.getResources(); |
| + int targetSize = res.getDimensionPixelSize(R.dimen.snippets_thumbnail_size); |
| + Bitmap scaledThumbnail = ThumbnailUtils.extractThumbnail( |
| + thumbnail, targetSize, targetSize, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); |
| + |
| + // Store the bitmap to skip the download task next time we display this snippet. |
| + snippet.setThumbnailBitmap(scaledThumbnail); |
| + |
| + // Cross-fade between the placeholder and the thumbnail. |
| + Drawable[] layers = {mThumbnailView.getDrawable(), |
| + new BitmapDrawable(mThumbnailView.getResources(), scaledThumbnail)}; |
| + TransitionDrawable transitionDrawable = new TransitionDrawable(layers); |
| + mThumbnailView.setImageDrawable(transitionDrawable); |
| + transitionDrawable.startTransition(FADE_IN_ANIMATION_TIME_MS); |
| } |
| @Override |