OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.ntp; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.content.res.Resources; |
| 9 import android.graphics.Bitmap; |
| 10 import android.graphics.Color; |
| 11 import android.graphics.Matrix; |
| 12 import android.util.AttributeSet; |
| 13 import android.widget.ImageView; |
| 14 |
| 15 import com.google.android.apps.chrome.R; |
| 16 |
| 17 /** |
| 18 * Displays a thumbnail for a most visited item on the NTP. |
| 19 */ |
| 20 public class MostVisitedThumbnail extends ImageView { |
| 21 |
| 22 private final int mDesiredWidth; |
| 23 private final int mDesiredHeight; |
| 24 private Bitmap mThumbnail; |
| 25 private Matrix mImageMatrix; |
| 26 |
| 27 /** |
| 28 * Constructor for inflating from XML. |
| 29 */ |
| 30 public MostVisitedThumbnail(Context context, AttributeSet attrs) { |
| 31 super(context, attrs); |
| 32 Resources res = getResources(); |
| 33 mDesiredWidth = res.getDimensionPixelSize(R.dimen.most_visited_thumbnail
_width); |
| 34 mDesiredHeight = res.getDimensionPixelSize(R.dimen.most_visited_thumbnai
l_height); |
| 35 } |
| 36 |
| 37 /** |
| 38 * Updates the thumbnail and trigger a redraw with the new thumbnail. |
| 39 */ |
| 40 void setThumbnail(Bitmap thumbnail) { |
| 41 mThumbnail = thumbnail; |
| 42 if (thumbnail != null) { |
| 43 setImageBitmap(thumbnail); |
| 44 setScaleType(ImageView.ScaleType.MATRIX); |
| 45 updateThumbnailMatrix(); |
| 46 } else { |
| 47 setBackgroundColor(Color.WHITE); |
| 48 setImageResource(R.drawable.most_visited_thumbnail_placeholder); |
| 49 setScaleType(ImageView.ScaleType.CENTER); |
| 50 } |
| 51 } |
| 52 |
| 53 /** |
| 54 * Updates the matrix used to scale the thumbnail when drawing it. This need
s to be called |
| 55 * whenever the thumbnail changes or this view's size changes. |
| 56 * |
| 57 * This matrix ensures that the thumbnail is anchored at the top left corner
of this view and |
| 58 * is scaled as small as possible while still covering the entire view. Surp
risingly, there's |
| 59 * no way to get this behavior using the other ImageView.ScaleTypes. |
| 60 */ |
| 61 private void updateThumbnailMatrix() { |
| 62 if (mThumbnail == null) return; |
| 63 |
| 64 if (mImageMatrix == null) mImageMatrix = new Matrix(); |
| 65 float widthScale = (float) getMeasuredWidth() / mThumbnail.getWidth(); |
| 66 float heightScale = (float) getMeasuredHeight() / mThumbnail.getHeight()
; |
| 67 float scale = Math.max(widthScale, heightScale); |
| 68 mImageMatrix.setScale(scale, scale); |
| 69 setImageMatrix(mImageMatrix); |
| 70 } |
| 71 |
| 72 @Override |
| 73 protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
| 74 super.onSizeChanged(w, h, oldw, oldh); |
| 75 updateThumbnailMatrix(); |
| 76 } |
| 77 |
| 78 /** |
| 79 * Maintains this view's aspect ratio, even when its width is constrained. W
e can't just use |
| 80 * android:adjustViewBounds, since that won't work when the source drawable
isn't set or when |
| 81 * it's the "missing thumbnail" gray circle, which has a different aspect ra
tio than thumbnails. |
| 82 */ |
| 83 @Override |
| 84 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| 85 int width = resolveSize(mDesiredWidth, widthMeasureSpec); |
| 86 int height; |
| 87 if (width == mDesiredWidth) { |
| 88 height = mDesiredHeight; |
| 89 } else { |
| 90 // The width is fixed. Find the height that keeps the proper aspect
ratio. |
| 91 height = Math.round((float) mDesiredHeight / mDesiredWidth * width); |
| 92 height = resolveSize(height, heightMeasureSpec); |
| 93 } |
| 94 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), |
| 95 MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); |
| 96 } |
| 97 } |
OLD | NEW |