自定义图片,切圆角、圆形,增加渐变颜色阴影
一、先上效果图
二、GitHub
代码地址,欢迎指正https://github.com/MNXP/RoundImageView
三、思路
1、图片切成圆角(圆形)
2、绘制一个带有渐变阴影的图形
3、融合圆角图片和阴影图形
四、实现(以下是以圆角为例,圆形的类似)
1)图片切成圆角
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);
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去掉
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setShadowLayer(0, 0, 0, 0xffffff);
canvas.drawBitmap(targetBitmap, mShadowRadius, mShadowRadius, mPaint);
4)使用(就是这么简单)
//圆角大小
//阴影大小
//是否圆形
//是否阴影
//阴影颜色
5)注意
因为绘制,阴影也会算入控件的大小
初始化参数
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完整代码
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);
}
}
如有意见和建议,及时沟通。