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