效果图:
一、 介绍Paint.setXfermode() 以及PorterDuffXfermode
public class WaveView extends View {
private Paint mWavePaint;
private Paint mCirclePaint;
private Canvas mCanvas;
private Bitmap mBitmap;
private int mWidth;
private int mHeight;
private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//设置mode 为XOR
public WaveView(Context context) {
super(context, null);
}
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
mWavePaint = new Paint();
mWavePaint.setColor(Color.parseColor("#33b5e5"));
mCirclePaint = new Paint();
mCirclePaint.setColor(Color.parseColor("#99cc00"));
mBitmap = Bitmap.createBitmap(500,500, Bitmap.Config.ARGB_8888); //生成一个bitmap
mCanvas = new Canvas(mBitmap);
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int 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) {
mWidth = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
mCanvas.drawCircle(100,100,100,mCirclePaint);
mCanvas.drawRect(100,100,300,300,mWavePaint);
canvas.drawBitmap(mBitmap,200,200,null);
super.onDraw(canvas);
}
}
可以看到 是我们现在自己的画布上铺了一个bitmap(这里可以理解canvas为桌子 bitmap为画纸,我们在bimap上画画), 然后在bitmap上画了 一个圆,和一个矩形。最后把我们的mBitmap画到系统的画布上(显示到屏幕上),得到了以下效果。
然后我们用setXfermode()方法给他设置一个mode,这里设置SRC_IN。效果如下:
总结各个模式如了下图:
我们要实现的是一个圆形的水波纹那种loadingview。。首要就是实现这个水波纹。这时候贝塞尔曲线就派上用场了。这里采用三阶贝塞尔, 不停地改变X 模拟水波效果。
public class WaveLoadingView extends View {
private final Paint mSRCPaint;
private Paint mPaint;
private Paint mTextPaint;
private Canvas mCanvas;
private Bitmap mBitmap;
private int y;
private int x;
private Path mPath;
private boolean isLeft;
private int mWidth;
private int mHeight;
private int mPercent;
private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
public WaveLoadingView(Context context) {
this(context, null);
}
public WaveLoadingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WaveLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setStrokeWidth(10);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.parseColor("#8800ff66"));
mPath = new Path();
mSRCPaint = new Paint();
mSRCPaint.setAntiAlias(true);
mSRCPaint.setColor(Color.parseColor("#88dddddd"));
mBitmap = Bitmap.createBitmap(getResources().getDimensionPixelSize(R.dimen.bg_size),
getResources().getDimensionPixelSize(R.dimen.bg_size), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int 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) {
mWidth = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
}
y = mHeight;
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
if (x > 100) {
isLeft = true;
} else if (x < 0) {
isLeft = false;
}
if (isLeft) {
x = x - 2;
} else {
x = x + 2;
}
mPath.reset();
if (mPercent != 0) {
y = (int) ((1 - mPercent /100f) *mHeight);
mPath.moveTo(0, y);
mPath.cubicTo(100 + x * 2, 50 + y, 100 + x * 2, y - 50, mWidth, y);
mPath.lineTo(mWidth, mHeight);
mPath.lineTo(0, mHeight);
mPath.close();
}
//清除掉图像 不然path会重叠
mBitmap.eraseColor(Color.parseColor("#00000000"));
mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);
mPaint.setXfermode(mMode);
mCanvas.drawPath(mPath, mPaint);
mPaint.setXfermode(null);
canvas.drawBitmap(mBitmap, 0, 0, null);
mTextPaint.setTextSize(80);
float strLen = mTextPaint.measureText(mPercent + "");
canvas.drawText(mPercent + "", mWidth / 2 - strLen / 2, mHeight / 2+15, mTextPaint);
mTextPaint.setTextSize(40);
canvas.drawText("%", mWidth / 2 + 50, mHeight / 2 - 20, mTextPaint);
postInvalidateDelayed(10);
}
public void setPercent(int percent){
mPercent = percent;
}
}
效果如下: