blob: 246cc96e415bae3385ce59c2146006ee3ecfac34 [file] [log] [blame]
Jin Caoe096b452014-07-28 10:49:24 -07001package com.android.ex.chips;
2
3import android.content.Context;
4import android.graphics.Bitmap;
5import android.graphics.BitmapShader;
6import android.graphics.Canvas;
7import android.graphics.Color;
8import android.graphics.Matrix;
9import android.graphics.Paint;
10import android.graphics.RectF;
11import android.graphics.Shader;
12import android.graphics.drawable.BitmapDrawable;
Jin Cao4db8ccc2014-07-30 10:11:07 -070013import android.graphics.drawable.Drawable;
14import android.graphics.drawable.StateListDrawable;
Jin Caoe096b452014-07-28 10:49:24 -070015import android.util.AttributeSet;
16import android.widget.ImageView;
17
18/**
19 * An ImageView class with a circle mask so that all images are drawn in a
20 * circle instead of a square.
21 */
22public class CircularImageView extends ImageView {
23 private static float circularImageBorder = 1f;
24
25 private final Matrix matrix;
26 private final RectF source;
27 private final RectF destination;
28 private final Paint bitmapPaint;
29 private final Paint borderPaint;
30
31 public CircularImageView(Context context) {
32 this(context, null, 0);
33 }
34
35 public CircularImageView(Context context, AttributeSet attrs) {
36 this(context, attrs, 0);
37 }
38
39 public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
40 super(context, attrs, defStyle);
41
42 matrix = new Matrix();
43 source = new RectF();
44 destination = new RectF();
45
46 bitmapPaint = new Paint();
47 bitmapPaint.setAntiAlias(true);
48 bitmapPaint.setFilterBitmap(true);
49 bitmapPaint.setDither(true);
50
51 borderPaint = new Paint();
52 borderPaint.setColor(Color.TRANSPARENT);
53 borderPaint.setStyle(Paint.Style.STROKE);
54 borderPaint.setStrokeWidth(circularImageBorder);
55 borderPaint.setAntiAlias(true);
56 }
57
58 @Override
59 protected void onDraw(Canvas canvas) {
Jin Cao4db8ccc2014-07-30 10:11:07 -070060 Drawable drawable = getDrawable();
61 BitmapDrawable bitmapDrawable = null;
62 // support state list drawable by getting the current state
63 if (drawable instanceof StateListDrawable) {
64 if (((StateListDrawable) drawable).getCurrent() != null) {
65 bitmapDrawable = (BitmapDrawable) drawable.getCurrent();
66 }
67 } else {
68 bitmapDrawable = (BitmapDrawable) drawable;
69 }
70
Jin Caoe096b452014-07-28 10:49:24 -070071 if (bitmapDrawable == null) {
72 return;
73 }
74 Bitmap bitmap = bitmapDrawable.getBitmap();
75 if (bitmap == null) {
76 return;
77 }
78
79 source.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
Jin Cao4db8ccc2014-07-30 10:11:07 -070080 destination.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(),
81 getHeight() - getPaddingBottom());
Jin Caoe096b452014-07-28 10:49:24 -070082
83 drawBitmapWithCircleOnCanvas(bitmap, canvas, source, destination);
84 }
85
86 /**
87 * Given the source bitmap and a canvas, draws the bitmap through a circular
88 * mask. Only draws a circle with diameter equal to the destination width.
89 *
90 * @param bitmap The source bitmap to draw.
91 * @param canvas The canvas to draw it on.
92 * @param source The source bound of the bitmap.
93 * @param dest The destination bound on the canvas.
94 */
95 public void drawBitmapWithCircleOnCanvas(Bitmap bitmap, Canvas canvas,
96 RectF source, RectF dest) {
97 // Draw bitmap through shader first.
98 BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
99 Shader.TileMode.CLAMP);
100 matrix.reset();
101
102 // Fit bitmap to bounds.
103 matrix.setRectToRect(source, dest, Matrix.ScaleToFit.FILL);
104
105 shader.setLocalMatrix(matrix);
106 bitmapPaint.setShader(shader);
107 canvas.drawCircle(dest.centerX(), dest.centerY(), dest.width() / 2f,
108 bitmapPaint);
109
110 // Then draw the border.
111 canvas.drawCircle(dest.centerX(), dest.centerY(),
112 dest.width() / 2f - circularImageBorder / 2, borderPaint);
113 }
114}