自定义圆形图片和圆角图片

在开发中,圆形图片和圆角图片应该是最常用的。当然,实现的方式也多种多样,甚至有些图片加载库中已经集成了这两种形状。本文采用自定义View的方式来实现这两种形状的图片。

自定义View的流程:

  1. 在res/values/attrs.xml中定义View的属性;
  2. 重写View的构造方法,并在其中获取属性值;
  3. 重写View的onDraw方法和onMeasure方法(具体看需求);

需求

通过属性区分圆形图片和圆角图片,同时支持设置圆形图片和圆角图片的边框宽度和颜色。所以我们只需要自定义四个属性即可:

在res/value/attrs.xml中定义属性:

1
2
3
4
5
6
7
8
9
10
<declare-styleable name="RoundImageView">
<!-- 是否为圆 默认为false, true表示圆, false表示圆角-->
<attr name="isCircle" format="boolean"/>
<!-- 圆角矩形圆角的角度 -->
<attr name="angle" format="dimension"/>
<!-- 边框的宽度 -->
<attr name="strokeWidth" format="dimension"/>
<!-- 边框的颜色 -->
<attr name="strokeColor" format="color"/>
</declare-styleable>

重写构造方法,并获取属性值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public RoundImageView(Context context) {
super(context);
}

public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
isCircle = typedArray.getBoolean(R.styleable.RoundImageView_isCircle, false);
angle = (int)typedArray.getDimension(R.styleable.RoundImageView_angle, 20);
strokeWidth = (int)typedArray.getDimension(R.styleable.RoundImageView_strokeWidth, 0);
strokeColor = typedArray.getColor(R.styleable.RoundImageView_strokeColor, Color.parseColor("#00000000"));
typedArray.recycle();
}

public RoundImageView(Context context, AttributeSet attrs, int theme) {
super(context, attrs, theme);
}

重写onDraw方法绘制圆形图片和圆角图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable != null) {
int width = getWidth();
int height = getHeight();
Bitmap bitmap = Bitmap.createScaledBitmap(drawableToBitmap(drawable), width, height, false);
int radius = Math.min(width, height) / 2;
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);

// 绘制图片边框
if (strokeWidth != 0) {
Paint boardPaint = new Paint();
boardPaint.setAntiAlias(true);
boardPaint.setColor(strokeColor);
boardPaint.setStyle(Paint.Style.STROKE);
boardPaint.setStrokeWidth(strokeWidth);
if (isCircle) {
canvas.drawCircle(width / 2, height / 2, radius - strokeWidth/2, boardPaint);
} else {
canvas.drawRoundRect(new RectF(strokeWidth, strokeWidth, width-strokeWidth, height-strokeWidth), angle, angle, boardPaint);
}
}

// 绘制图片(注意:绘制的图片大小要考虑边框,否则将覆盖边框)
if (isCircle) {
canvas.drawCircle(width / 2, height / 2, radius - strokeWidth, paint);
} else {
canvas.drawRoundRect(new RectF(strokeWidth, strokeWidth, width-strokeWidth, height-strokeWidth), angle, angle, paint);
}
} else {
super.onDraw(canvas);
}
}

/**
* 将Drawable转换为Bitmap
* /
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.draw(canvas);
return bitmap;
}
}

使用

在xml文件中使用RoundImageView,并设置相应的属性即可。

1
2
3
4
5
6
7
8
9
10
<com.sxu.roundimagedemo.RoundImageView
android:id="@+id/icon_image4"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginTop="15dp"
android:scaleType="centerCrop"
app:strokeColor="#40000000"
app:strokeWidth="4dp"
app:angle="10dp"
android:src="@drawable/icon"/>
,