android的图像混合模式xfermode可以画出一些特殊效果,如下图:
下面是作出上图效果的示例代码:
package hello.android;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.util.AttributeSet;
import android.view.View;
public class XfermodeView extends View {
private Paint mPaint;
private Xfermode mXfermode;
private Bitmap mSrcBitmap;
private Bitmap mDstBitmap;
public XfermodeView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mXfermode = new PorterDuffXfermode(Mode.SRC_IN);
}
@Override
protected void onDraw(Canvas canvas) {
int width = canvas.getWidth();
int height = canvas.getHeight();
if (mDstBitmap == null || mDstBitmap.getWidth() != width
|| mDstBitmap.getHeight() != height) {
mDstBitmap = createDstBitmap(width, height);
}
if (mSrcBitmap == null || mSrcBitmap.getWidth() != width
|| mSrcBitmap.getHeight() != height) {
mSrcBitmap = createSrcBitmap(width, height);
}
int saveCount = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);
mPaint.setXfermode(null);
canvas.drawBitmap(mDstBitmap, 0, 0, mPaint);
mPaint.setXfermode(mXfermode);
canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);
canvas.restoreToCount(saveCount);
// 重点1:canvas.saveLayer和canvas.restoreToCount是必须的
// 在这两行代码之间完成作图
// 似乎这两行代码完成了图像混合
// 重点2:为什么不在onDraw中直接canvas.drawCircle和canvas.drawRect;
// 这会导致图像混合只发生在canvas.drawRect的区域内,
// 而不是整个canvas的区域内,就得不到示例图片的效果。
}
private Bitmap createDstBitmap(int width, int height) {
int size = Math.min(width, height);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
mPaint.setColor(Color.YELLOW);
canvas.drawCircle(width / 2.0f, height / 2.0f, size / 4.0f, mPaint);
return bitmap;
}
private Bitmap createSrcBitmap(int width, int height) {
int size = Math.min(width, height);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
mPaint.setColor(Color.BLUE);
canvas.drawRect(width / 2.0f, height / 2.0f, width / 2.0f + size / 2.0f, height / 2.0f
+ size / 2.0f, mPaint);
return bitmap;
}
}