实现圆形ImageView方法很多,常见的就是利用BitmapShader或Xfermode来实现。我们还可以用自定义属性来自定义圆形边框。
定义自定义属性
在values文件夹中新建attrs.xml,定义边框颜色、边框宽度、实现方式。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
<attr name="draw_style" format="enum" >
<enum name="Xfermode" value="0"/>
<enum name="BitmapShader" value="1"/>
</attr>
</declare-styleable>
</resources>
在layout文件中的自定义属性设置
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context="wfz.mycircleimageview.MainActivity">
<wfz.mycircleimageview.CircleImageView
android:layout_marginTop="50dp"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="@drawable/butterfly_lg"
app:draw_style="Xfermode"
app:border_width="3dp"
app:border_color="@color/colorPrimary"/>
<wfz.mycircleimageview.CircleImageView
android:layout_marginTop="50dp"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="@drawable/butterfly_lg"
app:draw_style="BitmapShader"
app:border_width="3dp"
app:border_color="@color/colorPrimary"/>
</LinearLayout>
获取自定义属性
在自定义view中获取自定义属性
public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CircleImageView, defStyleAttr, 0);
mBorderWidth = a.getDimensionPixelSize(
R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
DEFAULT_BORDER_COLOR);
drawStyle = a.getInt(R.styleable.CircleImageView_draw_style, Xfermode);
Log.d("CircleImageView", "drawStyle-->"+drawStyle);
a.recycle();
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
}
绘制圆形ImageView
protected void onDraw(Canvas canvas) {
Bitmap bitmap = getBitmapFromDrawable(getDrawable());
if (bitmap == null)
return;
if (drawStyle == Xfermode)
drawCircleBitmapByXfermode(canvas, bitmap);
else
drawCircleBitmapByBitmapShader(canvas, bitmap);
// 绘边框
if (mBorderWidth != 0) {
canvas.drawCircle(width / 2, height / 2, r + mBorderWidth / 2 - 1,
mBorderPaint);
}
}
Xfermode的方式实现
clear应该是透明没东西才对
private void drawCircleBitmapByXfermode(Canvas canvas, Bitmap bitmap) {
Log.d("CircleImageView", "drawCircleBitmapByXfermode");
Paint cachePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
int sv = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);
canvas.drawCircle(width / 2, height / 2, r, cachePaint);
cachePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Matrix matrix = getImageMatrix(bitmap);
if (matrix != null)
canvas.concat(matrix);
canvas.drawBitmap(bitmap, 0, 0, cachePaint);
canvas.restoreToCount(sv);
}
BitmapShader的方式实现
private void drawCircleBitmapByBitmapShader(Canvas canvas, Bitmap bitmap) {
Log.d("CircleImageView", "drawCircleBitmapByBitmapShader");
Paint paint = new Paint();
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Matrix matrix = getImageMatrix(bitmap);
if (matrix != null)
bitmapShader.setLocalMatrix(matrix);
paint.setShader(bitmapShader);
canvas.drawCircle(width / 2, height / 2, r, paint);
}