Android自定义图片圆角,增加渐变阴影

自定义图片,切圆角、圆形,增加渐变颜色阴影


一、先上效果图

效果图

二、GitHub

代码地址,欢迎指正https://github.com/MNXP/RoundImageView

三、思路

1、图片切成圆角(圆形)
2、绘制一个带有渐变阴影的图形
3、融合圆角图片和阴影图形

四、实现(以下是以圆角为例,圆形的类似)

1)图片切成圆角

1
2
3
4
5
6
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Bitmap targetBitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
Canvas targetCanvas = new Canvas(targetBitmap);
mPaint.setShader(bitmapShader);
RectF rect = new RectF(0, 0, imageWidth, imageHeight);
targetCanvas.drawRoundRect(rect, mRadius, mRadius, mPaint);
形成的效果图

圆角

2)绘制一个带有渐变阴影的图形

设置渐变阴影 mPaint.setShadowLayer(mShadowRadius, 1, 1, mShadowColor); 
第一个参数:阴影大小;
第二个参数:X轴偏移量;
第三个参数:Y轴偏移量;
第四个参数:阴影颜色;
X、Y轴偏移量都为1时是四周都有阴影

设置paint的颜色和阴影颜色一致,不然会出现黑边   mPaint.setColor(mShadowColor);
1
2
3
4
5
6
mPaint.setColor(mShadowColor);
mPaint.setShadowLayer(mShadowRadius, 1, 1, mShadowColor);
Bitmap target = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);
RectF rectF = new RectF(mShadowRadius, mShadowRadius, width - mShadowRadius, height - mShadowRadius);
canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);

阴影效果图

3)融合圆角图片和阴影图形

上代码之前先上一个图像合成效果示意图

图像合成效果示意图

好了,上面就是图像融合的一些方式,我用的是SRC_OVER。记得把paint设置的shadowLayer去掉
1
2
3
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setShadowLayer(0, 0, 0, 0xffffff);
canvas.drawBitmap(targetBitmap, mShadowRadius, mShadowRadius, mPaint);

最终效果图

4)使用(就是这么简单)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<declare-styleable name="RoundImageView">
<attr name="image_radius" format="dimension" />//圆角大小
<attr name="image_shadow_radius" format="dimension" />//阴影大小
<attr name="image_circle" format="boolean" />//是否圆形
<attr name="image_shadow" format="boolean" />//是否阴影
<attr name="shadow_color" format="integer"/>//阴影颜色
</declare-styleable>


<com.xiangpan.roundimageview.RoundImageView
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/tu"
app:image_shadow="true"
app:image_radius = "16dp"
app:image_shadow_radius="20dp"/>

5)注意

因为绘制,阴影也会算入控件的大小

示意图

初始化参数
1
2
3
4
5
6
7
8
width = canvas.getWidth() - getPaddingLeft() - getPaddingRight();//控件实际大小
height = canvas.getHeight() - getPaddingTop() - getPaddingBottom();
if (!mIsShadow)
mShadowRadius = 0;
imageWidth = width - (int) mShadowRadius * 2;//图片实际宽度
imageHeight = height - (int) mShadowRadius * 2;//图片实际高度
Bitmap image = drawableToBitmap(getDrawable());
Bitmap reSizeImage = reSizeImage(image, imageWidth, imageHeight);

6)RoundImageView完整代码

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

public class RoundImageView extends AppCompatImageView {


public RoundImageView(final Context context) {
this(context, null);
}

public RoundImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setScaleType(ScaleType.FIT_XY);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.RoundImageView, defStyle, 0);
if (ta!=null){
mRadius = ta.getDimension(R.styleable.RoundImageView_image_radius, 0);
mShadowRadius = ta.getDimension(R.styleable.RoundImageView_image_shadow_radius, 0);
mIsCircle = ta.getBoolean(R.styleable.RoundImageView_image_circle, false);
mIsShadow = ta.getBoolean(R.styleable.RoundImageView_image_shadow, false);
mShadowColor = ta.getInteger(R.styleable.RoundImageView_shadow_color,0xffe4e4e4);
ta.recycle();
}else {
mRadius = 0;
mShadowRadius = 0;
mIsCircle = false;
mIsShadow = false;
mShadowColor = 0xffe4e4e4;
}

}


private float mRadius;
private float mShadowRadius;
private int mShadowColor;
private boolean mIsCircle;
private boolean mIsShadow;
private int width;
private int height;
private int imageWidth;
private int imageHeight;
private Paint mPaint;

@Override
public void onDraw(Canvas canvas) {
width = canvas.getWidth() - getPaddingLeft() - getPaddingRight();//控件实际大小
height = canvas.getHeight() - getPaddingTop() - getPaddingBottom();

if (!mIsShadow)
mShadowRadius = 0;

imageWidth = width - (int) mShadowRadius * 2;
imageHeight = height - (int) mShadowRadius * 2;

Bitmap image = drawableToBitmap(getDrawable());
Bitmap reSizeImage = reSizeImage(image, imageWidth, imageHeight);
initPaint();


if (mIsCircle) {
canvas.drawBitmap(createCircleImage(reSizeImage),
getPaddingLeft(), getPaddingTop(), null);

} else {
canvas.drawBitmap(createRoundImage(reSizeImage),
getPaddingLeft(), getPaddingTop(), null);
}
}

private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
}


private Bitmap createRoundImage(Bitmap bitmap) {
if (bitmap == null) {
throw new NullPointerException("Bitmap can't be null");
}
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Bitmap targetBitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
Canvas targetCanvas = new Canvas(targetBitmap);

mPaint.setShader(bitmapShader);

RectF rect = new RectF(0, 0, imageWidth, imageHeight);
targetCanvas.drawRoundRect(rect, mRadius, mRadius, mPaint);

if (mIsShadow){
mPaint.setShader(null);
mPaint.setColor(mShadowColor);
mPaint.setShadowLayer(mShadowRadius, 1, 1, mShadowColor);
Bitmap target = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);

RectF rectF = new RectF(mShadowRadius, mShadowRadius, width - mShadowRadius, height - mShadowRadius);
canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setShadowLayer(0, 0, 0, 0xffffff);
canvas.drawBitmap(targetBitmap, mShadowRadius, mShadowRadius, mPaint);
return target;
}else {
return targetBitmap;
}

}


private Bitmap createCircleImage(Bitmap bitmap) {
if (bitmap == null) {
throw new NullPointerException("Bitmap can't be null");
}
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Bitmap targetBitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
Canvas targetCanvas = new Canvas(targetBitmap);

mPaint.setShader(bitmapShader);

targetCanvas.drawCircle(imageWidth / 2, imageWidth / 2, Math.min(imageWidth, imageHeight) / 2,
mPaint);

if (mIsShadow){
mPaint.setShader(null);
mPaint.setColor(mShadowColor);
mPaint.setShadowLayer(mShadowRadius, 1, 1, mShadowColor);
Bitmap target = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);

canvas.drawCircle(width / 2, height / 2, Math.min(imageWidth, imageHeight) / 2,
mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setShadowLayer(0, 0, 0, 0xffffff);
canvas.drawBitmap(targetBitmap, mShadowRadius, mShadowRadius, mPaint);
return target;
}else {
return targetBitmap;
}

}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}

/**
* drawable转bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicHeight(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}

/**
* 重设Bitmap的宽高
*
* @param bitmap
* @param newWidth
* @param newHeight
* @return
*/
private Bitmap reSizeImage(Bitmap bitmap, int newWidth, int newHeight) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// 计算出缩放比
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 矩阵缩放bitmap
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
}


}

如有意见和建议,及时沟通。

0%