最近一段时间学了很多关于圆角矩形或者圆角图片制作的文章,写的都很好,但是每次一学完都会做,但是过段时间又不记得该怎么写代码了,反思了一下,是自己只是在看,并没有真正的消化,所以还不算自己的东西,于是今天又把大神的代码又看了看,自己总结,自己再写一遍,算是明白了吧,也想写个文章记录一下,方便下次寻找,也可以分享出来。
Xfermode是android画笔Paint可以设置的一种画笔属性,具体就是可以把两张图片进行组合,根据设置的形式,可以组合多种形式,具体大家看图:
这里用的就是SrcIn模式,大致思路就是先绘制一个圆或者圆角矩形,然后再绘制我们的图片,然后根据上面的SrcIn模式,最终就绘制出了圆形图片或者圆角矩形。android里面把先绘制的图片视为Src,后绘制的是Dst。
具体代码如下,里面说的很详细了。
package com.fanxl.roundview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
public class RoundView extends View {
private Bitmap src;
private Bitmap out;
private int width;
private int height;
private int type;
private static final int TYPE_CIRCLE = 0;
private static final int TYPE_ROUND = 1;
public RoundView(Context context) {
this(context, null);
}
public RoundView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//自己计算控件的宽高
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
int imgWidth = src.getWidth() + getPaddingLeft()
+ getPaddingRight();
if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(widthSize, imgWidth);
} else {
width = imgWidth;
}
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
int imgHeight = src.getHeight() + getPaddingTop()
+ getPaddingBottom();
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(heightSize, imgHeight);
} else {
height = imgHeight;
}
}
//根据要绘制的类型设置最终自定义控件的宽高
switch (type) {
case TYPE_CIRCLE:
int min = Math.min(width, height);
setMeasuredDimension(min, min);
break;
case TYPE_ROUND:
setMeasuredDimension(width, height);
break;
}
}
@SuppressLint("NewApi")
private void initView() {
// 禁止硬件加速,硬件加速会有一些问题,这里禁用掉
setLayerType(LAYER_TYPE_SOFTWARE, null);
src = BitmapFactory.decodeResource(getResources(), R.drawable.dd);
//设置类型,是圆角图片还是圆角矩形
type = TYPE_CIRCLE;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
xmodeImage();
//把画好画的画布放到自定义的画板上面
canvas.drawBitmap(out, 0, 0, null);
}
private void xmodeImage() {
//根据原始的图片创建一个画布
out = Bitmap.createBitmap(width, height, Config.ARGB_8888);
//创建一个画板,在画布的基础上
Canvas canvas = new Canvas(out);
//创建一个画笔
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
switch (type) {
case TYPE_ROUND:
//开始在有画板的画布上用画笔作画了,这里画了一个圆角矩形
canvas.drawRoundRect(new RectF(0, 0, width, height),
60, 60, paint);
break;
case TYPE_CIRCLE:
//画圆,取宽高的最小值作为圆的直径
int min = Math.min(width, height);
//开始画圆
canvas.drawCircle(min/2, min/2, min/2, paint);
break;
}
//设置Xfermode画笔模式为SRC_IN
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
//然后有画了一个图片,最终实现两个图像的叠加
canvas.drawBitmap(src, 0, 0, paint);
}
}
最终效果: