package com.android.ex.chips; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.util.AttributeSet; import android.widget.ImageView; /** * An ImageView class with a circle mask so that all images are drawn in a * circle instead of a square. */ public class CircularImageView extends ImageView { private static float circularImageBorder = 1f; private final Matrix matrix; private final RectF source; private final RectF destination; private final Paint bitmapPaint; private final Paint borderPaint; public CircularImageView(Context context) { this(context, null, 0); } public CircularImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircularImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); matrix = new Matrix(); source = new RectF(); destination = new RectF(); bitmapPaint = new Paint(); bitmapPaint.setAntiAlias(true); bitmapPaint.setFilterBitmap(true); bitmapPaint.setDither(true); borderPaint = new Paint(); borderPaint.setColor(Color.TRANSPARENT); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(circularImageBorder); borderPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); BitmapDrawable bitmapDrawable = null; // support state list drawable by getting the current state if (drawable instanceof StateListDrawable) { if (((StateListDrawable) drawable).getCurrent() != null) { bitmapDrawable = (BitmapDrawable) drawable.getCurrent(); } } else { bitmapDrawable = (BitmapDrawable) drawable; } if (bitmapDrawable == null) { return; } Bitmap bitmap = bitmapDrawable.getBitmap(); if (bitmap == null) { return; } source.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); destination.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); drawBitmapWithCircleOnCanvas(bitmap, canvas, source, destination); } /** * Given the source bitmap and a canvas, draws the bitmap through a circular * mask. Only draws a circle with diameter equal to the destination width. * * @param bitmap The source bitmap to draw. * @param canvas The canvas to draw it on. * @param source The source bound of the bitmap. * @param dest The destination bound on the canvas. */ public void drawBitmapWithCircleOnCanvas(Bitmap bitmap, Canvas canvas, RectF source, RectF dest) { // Draw bitmap through shader first. BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); matrix.reset(); // Fit bitmap to bounds. matrix.setRectToRect(source, dest, Matrix.ScaleToFit.FILL); shader.setLocalMatrix(matrix); bitmapPaint.setShader(shader); canvas.drawCircle(dest.centerX(), dest.centerY(), dest.width() / 2f, bitmapPaint); // Then draw the border. canvas.drawCircle(dest.centerX(), dest.centerY(), dest.width() / 2f - circularImageBorder / 2, borderPaint); } }