1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3.widget;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Rect;
22 import android.graphics.RectF;
23 import android.graphics.drawable.Drawable;
24 import android.util.AttributeSet;
25 import android.view.View;
26 
27 /**
28  * View that draws a bitmap horizontally centered. If the image width is greater than the view
29  * width, the image is scaled down appropriately.
30  */
31 public class WidgetImageView extends View {
32 
33     private final RectF mDstRectF = new RectF();
34     private Drawable mDrawable;
35 
WidgetImageView(Context context)36     public WidgetImageView(Context context) {
37         this(context, null);
38     }
39 
WidgetImageView(Context context, AttributeSet attrs)40     public WidgetImageView(Context context, AttributeSet attrs) {
41         this(context, attrs, 0);
42     }
43 
WidgetImageView(Context context, AttributeSet attrs, int defStyle)44     public WidgetImageView(Context context, AttributeSet attrs, int defStyle) {
45         super(context, attrs, defStyle);
46     }
47 
48     /** Set the drawable to use for this view. */
setDrawable(Drawable drawable)49     public void setDrawable(Drawable drawable) {
50         mDrawable = drawable;
51         invalidate();
52     }
53 
getDrawable()54     public Drawable getDrawable() {
55         return mDrawable;
56     }
57 
58     @Override
onDraw(Canvas canvas)59     protected void onDraw(Canvas canvas) {
60         if (mDrawable != null) {
61             updateDstRectF();
62             mDrawable.setBounds(getBitmapBounds());
63             mDrawable.draw(canvas);
64         }
65     }
66 
67     /**
68      * Prevents the inefficient alpha view rendering.
69      */
70     @Override
hasOverlappingRendering()71     public boolean hasOverlappingRendering() {
72         return false;
73     }
74 
updateDstRectF()75     private void updateDstRectF() {
76         float myWidth = getWidth();
77         float myHeight = getHeight();
78         final float bitmapWidth = mDrawable.getIntrinsicWidth();
79         final float bitmapHeight = mDrawable.getIntrinsicHeight();
80         final float bitmapAspectRatio = bitmapWidth / bitmapHeight;
81         final float containerAspectRatio = myWidth / myHeight;
82 
83         // Scale by width if image has larger aspect ratio than the container else by height; and
84         // avoid cropping the previews
85         final float scale = bitmapAspectRatio > containerAspectRatio ? myWidth / bitmapWidth
86                 : myHeight / bitmapHeight;
87 
88         final float scaledWidth = bitmapWidth * scale;
89         final float scaledHeight = bitmapHeight * scale;
90 
91         // Avoid cropping by checking bounds after scaling.
92         if (scaledWidth > myWidth) {
93             mDstRectF.left = 0;
94             mDstRectF.right = scaledWidth;
95         } else {
96             mDstRectF.left = (myWidth - scaledWidth) / 2;
97             mDstRectF.right = (myWidth + scaledWidth) / 2;
98         }
99         if (scaledHeight > myHeight) {
100             mDstRectF.top = 0;
101             mDstRectF.bottom = scaledHeight;
102         } else {
103             mDstRectF.top = (myHeight - scaledHeight) / 2;
104             mDstRectF.bottom = (myHeight + scaledHeight) / 2;
105         }
106     }
107 
108     /**
109      * @return the bounds where the image was drawn.
110      */
getBitmapBounds()111     public Rect getBitmapBounds() {
112         updateDstRectF();
113         Rect rect = new Rect();
114         mDstRectF.round(rect);
115         return rect;
116     }
117 }
118