补充基础知识请点我http://blog.csdn.net/t12x3456/article/details/10432935
新建一个类继承View,继承他的俩构造器和onDraw以及onMeasure方法。PorterDuff必须画在bitmap上。步骤:
// 创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
mBitmap=Bitmap.createBitmap(mWith,mHeight, Bitmap.Config.ARGB_8888);
// 绘制一个由指定位图构成的画布
canvasBit=new Canvas(mBitmap);
// 可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
mPaintSrc.setXfermode(mode);
// 图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
canvasBit.drawRect(10, 200, mWith/2, mHeight/2, mPaintSrc);
// 将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
canvas.drawBitmap(mBitmap,0,0,null);
该实例的效果图(PorterDuff.Mode.SRC_OVER)
参考:API中提供的能够进行的16中操作种类(PorterDuff.Mode为枚举类,一共有16个枚举值)
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色
全部代码
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.example.laowang.android0916canvas_.R;
/**
* Created by Administrator on 2015/9/17.
*/
public class MyBitmapView2 extends View {
private int mWith;
private int mHeight;
private Paint mPaintSrc;
private Paint mPaintDst;
private Bitmap mBitmap;
private Canvas canvasBit;
public MyBitmapView2(Context context) {
super(context);
}
public MyBitmapView2(Context context, AttributeSet attrs) {
super(context, attrs);
// 初始化bitmap对象
mBitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.dogno);
mPaintSrc=new Paint();
mPaintDst=new Paint();
mPaintSrc.setColor(Color.argb(0xff, 0x63, 0xAA, 0xFF));//自定义颜色
mPaintSrc.setAntiAlias(true);
mPaintDst.setColor(Color.argb(0xff, 0xFF, 0xCF, 0x42));
mPaintDst.setAntiAlias(true);
// 可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
mPaintSrc.setXfermode(mode);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWith, mHeight);
// 创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
mBitmap=Bitmap.createBitmap(mWith,mHeight, Bitmap.Config.ARGB_8888);
// 绘制一个由指定位图构成的画布
canvasBit=new Canvas(mBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GRAY);
// 图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
canvasBit.drawRect(10, 200, mWith/2, mHeight/2, mPaintSrc);
// 将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
canvas.drawBitmap(mBitmap,0,0,null);
}
}
在实例1的基础上面加以修改,达到这个效果,鼠标按下后拖动将蓝色部分去掉,点击保存照片将照片保存。
首先添加权限
"android.permission.READ_EXTERNAL_STORAGE"/>
"android.permission.WRITE_EXTERNAL_STORAGE"/>
创建一个Bitmap背景对象,在构造器中初始化。
mBitmapBackground=BitmapFactory.decodeResource(getResources(),R.mipmap.nurse);
在onMeasure方法中获得他的宽高
mImageWith = mBitmapBackground.getWidth();
mImageHeight = mBitmapBackground.getHeight();
设置画笔移动时的效果!!!!!!
mPaintDst.setAntiAlias(true);
// 可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
mPaintDst.setXfermode(mode);//mPaintDst加上以后加图片处理,所以后面话圆的时候要用这个画笔
mPaintDst.setStrokeJoin(Paint.Join.ROUND);//圆角 连接时使用的方式
mPaintDst.setStrokeCap(Paint.Cap.ROUND);//圆角 覆盖式使用的方式
mPaintDst.setStyle(Paint.Style.STROKE);//要用上面的方法必须将画笔设置成STROKE或者FILL_AND_STROKE
将背景图片添加到画布中,通过path画出线条
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 添加背景图片,拉伸到屏幕大小
canvas.drawBitmap(mBitmapBackground, new Rect(0, 0, mImageWith, mImageHeight), new Rect(0, 0, mWith, mHeight), null);
// 图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
// canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
canvasBit.drawRect(0, 0, mWith, mHeight, mPaintSrc);//先画底层的
// 通过Path实现画多个圆,不取消前面画的圆
canvasBit.drawPath(mPath, mPaintDst);
// 将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
canvas.drawBitmap(mBitmap, 0, 0, null);
}
添加touch效果
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
mPath.moveTo(x, y);
invalidate();//刷新
old_x = x;
old_y = y;
return true;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
mPath.moveTo(old_x, old_y);
mPath.lineTo(x, y);
invalidate();
old_y = y;
old_x = x;
return true;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}
修改后的代码
package com.example.laowang.myview2;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2015/9/18.
*/
public class MyBitmapView extends View {
private int mWith;
private int mHeight;
private Paint mPaintSrc;
private Paint mPaintDst;
private Bitmap mBitmap;
private Bitmap mBitmapBackground;
private Canvas canvasBit;
private int mImageWith;
private int mImageHeight;
private Path mPath;
private float x;
private float y;
private float old_y;
private float old_x;
public MyBitmapView(Context context) {
super(context);
}
public MyBitmapView(Context context, AttributeSet attrs) {
super(context, attrs);
mPath = new Path();
mPaintSrc = new Paint();
mPaintDst = new Paint();
mPaintSrc.setColor(Color.argb(0xff, 0x63, 0xAA, 0xFF));//自定义颜色
mPaintSrc.setAntiAlias(true);
mPaintDst.setColor(Color.argb(0xff, 0xFF, 0xCF, 0x42));
mPaintDst.setStrokeWidth(30);
mPaintDst.setAntiAlias(true);
// 可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
mPaintDst.setXfermode(mode);//mPaintDst加上以后加图片处理,所以后面话圆的时候要用这个画笔
mPaintDst.setStrokeJoin(Paint.Join.ROUND);//圆角 连接时使用的方式
mPaintDst.setStrokeCap(Paint.Cap.ROUND);//圆角 覆盖式使用的方式
mPaintDst.setStyle(Paint.Style.STROKE);//要用上面的方法必须将画笔设置成STROKE或者FILL_AND_STROKE
// 背景图片 mBitmapBackground=BitmapFactory.decodeResource(getResources(),R.mipmap.dog);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWith, mHeight);
// 创建一个宽with高height的新位图,第三个参数传位图配置,这里的配置意思为:每个像素被存储在4个字节中。
mBitmap = Bitmap.createBitmap(mWith, mHeight, Bitmap.Config.ARGB_8888);
// 绘制一个由指定位图构成的画布
canvasBit = new Canvas(mBitmap);
mImageWith = mBitmapBackground.getWidth();
mImageHeight = mBitmapBackground.getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 添加背景图片,拉伸到屏幕大小
canvas.drawBitmap(mBitmapBackground, new Rect(0, 0, mImageWith, mImageHeight), new Rect(0, 0, mWith, mHeight), null);
// 图像渲染只能在bitmap中进行,通过canvasBit对bitmap进行渲染操作
// canvasBit.drawCircle(mWith / 2, mHeight / 2, 250, mPaintDst);
canvasBit.drawRect(0, 0, mWith, mHeight, mPaintSrc);//先画底层的
// 通过Path实现画多个圆,不取消前面画的圆
canvasBit.drawPath(mPath, mPaintDst);
// 将位图放在画布中,在进行了渲染操作的位图放到画布中显示出来。
canvas.drawBitmap(mBitmap, 0, 0, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
mPath.moveTo(x, y);
invalidate();//刷新
old_x = x;
old_y = y;
return true;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
mPath.moveTo(old_x, old_y);
mPath.lineTo(x, y);
invalidate();
old_y = y;
old_x = x;
return true;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}
}