Android自定義圖片圓角,增加漸變陰影
阿新 • • 發佈:2018-12-31
自定義圖片,切圓角、圓形,增加漸變顏色陰影
一、先上效果圖
二、GitHub
三、思路
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)使用(就是這麼簡單)
<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)注意
因為繪製,陰影也會算入控制元件的大小
初始化引數
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);
}
}
如有意見和建議,及時溝通。