android画笔画布基本方法,android 画布,画笔,综合使用,可实现简单的画板

本文详细介绍了如何在Android中创建一个自定义View,实现画板功能,包括画笔、橡皮擦的使用,以及透明度的设置。作者在编写过程中遇到透明画笔路径不显示的问题,并最终找到了解决方案,即通过设置PorterDuff.Mode.SRC_OUT模式来实现橡皮擦效果。代码示例展示了关键的初始化和触摸事件处理过程。
摘要由CSDN通过智能技术生成

编写之前需要了解的知识点

自定义 view

画笔 paint

路径 path

画布 canvas

别写这个的时候遇见好大的一个坑,就是使用canvas时,使用paint画笔具有透明度,每次都是调试不出来这个带透明的画笔,其实很简单的问题,让我疑惑了一天。

以上就是我在编写的时候遇见的问题

先上图,看一下带透明度的线4d791eebefe82fffd9aa8af08bcb2f76.png

本节主要讲解最基础的部分

private static final int INIT_PEN_WIDTH = 80;

/**

* 画笔的模式

*/

public static final int MODE_PEN = 0;

public static final int MODE_ERASER = 1;

private float mX, mY;

private float TOUCH_TOLERANCE = 4;

private int mMode;

private Paint mPenPaint;//画画的画笔

private Paint mEraserPaint;//用于橡皮擦的画笔

private int mPenWidth;//用于保存当前的画笔宽度

private int mPenColor;//用于保存当前画笔的颜色

private Paint.Style mPenStyle; //当前画笔的样式

private int mEraserWidth = 50;//用于保存当前橡皮擦的宽度

private Canvas mPenCanvas;//用于画画的画板

private Bitmap mPenBitmap;//一个空白的图片,通过画板控制 mPenCanvas;

以上是画板的参数

初始化橡皮擦的画笔属性

mEraserPaint = new Paint();

mEraserPaint.setStrokeWidth(mEraserWidth);

mEraserPaint.setAlpha(0);

//这个属性是设置paint为橡皮擦重中之重

//这是重点

mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));

//上面这句代码是橡皮擦设置的重点(重要的事是不是一定要说三遍)

mEraserPaint.setAntiAlias(true);

mEraserPaint.setDither(true);

mEraserPaint.setStyle(Paint.Style.STROKE);

mEraserPaint.setStrokeJoin(Paint.Join.ROUND);

mEraserPaint.setStrokeWidth(mEraserWidth);这里橡皮擦的画笔初始化,所要求的知识点比较全面,如果把这个搞明白了,画笔Paint的基本使用你就没有问题了。

下面是对画画的画笔进行初始化

mPenPaint = new Paint();

mPenPaint.setAntiAlias(true);

mPenPaint.setStrokeWidth(mPenWidth);

mPenPaint.setStyle(mPenStyle);

mPenPaint.setColor(mPenColor);

mPenPaint.setStrokeCap(Paint.Cap.ROUND);

mPenPaint.setStrokeJoin(Paint.Join.ROUND);

下面呢对画布进行初始化操作

//创建一个画布背景

mPenBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

//用于操作的画布

mPenCanvas = new Canvas(mPenBitmap);

下面的具体操作就是在OnTouchListener的滑动事件对手势进行操作

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

touchDown(event);

break;

case MotionEvent.ACTION_UP:

touchUp(event);

break;

case MotionEvent.ACTION_MOVE:

touchMove(event);

break;

}

return true;

}

然后就是touchDown方法内的内容,里面主要创建一个每次操作的启示初始化工作;

private voidtouchDown(MotionEvent event) {

floatx = event.getX();floaty = event.getY();mX= x;mY= y;DrawParams drawParams = newDrawParams();if(mMode== MODE_PEN) {

drawParams.paint= newPaint(mPenPaint);} else if(mMode== MODE_ERASER) {

drawParams.paint= newPaint(mEraserPaint);}

drawParams.path= newPath();drawParams.path.moveTo(x,y);//mPath.moveTo(x, y);mDrawList.add(drawParams);invalidate();}

下面的就是touchMove方法是比较重点的地方

private voidtouchMove(MotionEvent event) {

floatx = event.getX();floaty = event.getY();floatdx = Math.abs(x - mX);floatdy = Math.abs(y - mY);if(dx >= TOUCH_TOLERANCE|| dy >= TOUCH_TOLERANCE) {mDrawList.get(mDrawList.size() - 1).path.quadTo(mX,mY,(x + mX) / 2,(y + mY) / 2);invalidate();}

mX= x;mY= y;}

下面是onDraw的具体方法

@Overrideprotected voidonDraw(Canvas canvas) {

initDraw();/*** 用于解决 使用透明色时,划线颜色一直加深的问题,该方法就是每次操作的时候都会把画板用橡皮擦清空内容* 然后在让保存的每次操作进行对画板的设置;*/mPenCanvas.drawBitmap(mPenBitmap,0,0,mEraserPaint);if(mDrawList.size() > 0)

for(inti = 0;i < mDrawList.size();i++) {

DrawParams drawParams = mDrawList.get(i);mPenCanvas.drawPath(drawParams.path,drawParams.paint);}

canvas.drawBitmap(mPenBitmap,0,0, null);super.onDraw(canvas);}

总感觉代码太过简单,所以没有描述过多。这都是基础。就是实现画笔带有透明度的时候总是 Path路径不带透明度,让我郁闷一天,后来才想到,只要加一行代码一切都解决。

上网查了好多资料都没有,在阳台抽烟忽悠一下想到的,真就是灵光一闪,答案就出来了。

下面我就把全部源码贡献,希望对你有帮助,我还会继续的扩展,我们老大要让我做一个带图片缩放,对图片进行绘画的功能软件,等完毕后,把工程上传让大家分享。

/**

* Created by mrqiu on 2017/4/3.

*/

public class DrawView extends View implements View.OnTouchListener {

private static final int INIT_PEN_WIDTH = 80;

/**

* 画笔的模式

*/

public static final int MODE_PEN = 0;

public static final int MODE_ERASER = 1;

private ArrayListmDrawList;//用于存储每次的操作

private float mX, mY;

private float TOUCH_TOLERANCE = 4;

private int mMode;

private Paint mPenPaint;//画画的画笔

private Paint mEraserPaint;//用于橡皮擦的画笔

private int mPenWidth;//用于保存当前的画笔宽度

private int mPenColor;//用于保存当前画笔的颜色

private Paint.Style mPenStyle; //当前画笔的样式

private int mEraserWidth = 50;//用于保存当前橡皮擦的宽度

private Canvas mPenCanvas;//用于画画的画板

private Bitmap mPenBitmap;//一个空白的图片,通过画板控制 mPenCanvas;

public DrawView(Context context) {

super(context);

init(context, null, 0);

}

public DrawView(Context context, AttributeSet attrs) {

super(context, attrs);

init(context, attrs, 0);

}

public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(context, attrs, defStyleAttr);

}

private void init(Context context, AttributeSet attrs, int defStyleAttr) {

mDrawList = new ArrayList<>();

mPenColor = Color.BLUE;

mPenStyle = Paint.Style.STROKE;

mPenWidth = INIT_PEN_WIDTH;

mPenPaint = new Paint();

mPenPaint.setAntiAlias(true);

mPenPaint.setStrokeWidth(mPenWidth);

mPenPaint.setStyle(mPenStyle);

mPenPaint.setColor(mPenColor);

mPenPaint.setStrokeCap(Paint.Cap.ROUND);

mPenPaint.setStrokeJoin(Paint.Join.ROUND);

mEraserPaint = new Paint();

mEraserPaint.setStrokeWidth(mEraserWidth);

mEraserPaint.setAlpha(0);

//这个属性是设置paint为橡皮擦重中之重

//这是重点

mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));

//上面这句代码是橡皮擦设置的重点(重要的事是不是一定要说三遍)

mEraserPaint.setAntiAlias(true);

mEraserPaint.setDither(true);

mEraserPaint.setStyle(Paint.Style.STROKE);

mEraserPaint.setStrokeJoin(Paint.Join.ROUND);

mEraserPaint.setStrokeWidth(mEraserWidth);

//创建一个画布背景

mPenBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

//用于操作的画布

mPenCanvas = new Canvas(mPenBitmap);

setOnTouchListener(this);

}

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

touchDown(event);

break;

case MotionEvent.ACTION_UP:

touchUp(event);

break;

case MotionEvent.ACTION_MOVE:

touchMove(event);

break;

}

return true;

}

private void touchMove(MotionEvent event) {

float x = event.getX();

float y = event.getY();

float dx = Math.abs(x - mX);

float dy = Math.abs(y - mY);

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {

//mPath.reset();

//mPath.moveTo(mX,mY);

//mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);

mDrawList.get(mDrawList.size() - 1).path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);

Log.i("touchMove", "touchMove: " + mX + ",mY=" + mY + "," + mDrawList.size());

invalidate();

}

mX = x;

mY = y;

}

private void touchUp(MotionEvent event) {

}

private void touchDown(MotionEvent event) {

float x = event.getX();

float y = event.getY();

mX = x;

mY = y;

DrawParams drawParams = new DrawParams();

if (mMode == MODE_PEN) {

drawParams.paint = new Paint(mPenPaint);

} else if (mMode == MODE_ERASER) {

drawParams.paint = new Paint(mEraserPaint);

}

drawParams.path = new Path();

drawParams.path.moveTo(x, y);

//mPath.moveTo(x, y);

mDrawList.add(drawParams);

invalidate();

}

public void setMode(int mode) {

mMode = mode;

}

public static class DrawParams {

Path path;

Paint paint;

}

private void initDraw() {

mPenCanvas.drawColor(Color.argb(0, 0, 0, 0));

}

@Override

protected void onDraw(Canvas canvas) {

initDraw();

/**

* 用于解决 使用透明色时,划线颜色一直加深的问题,该方法就是每次操作的时候都会把画板用橡皮擦清空内容

* 然后在让保存的每次操作进行对画板的设置;

*/

mPenCanvas.drawBitmap(mPenBitmap, 0, 0, mEraserPaint);

if (mDrawList.size() > 0)

for (int i = 0; i < mDrawList.size(); i++) {

DrawParams drawParams = mDrawList.get(i);

mPenCanvas.drawPath(drawParams.path, drawParams.paint);

}

canvas.drawBitmap(mPenBitmap, 0, 0, null);

super.onDraw(canvas);

}

public void setPenColor(int penColor) {

this.mPenColor = penColor;

mPenPaint.setColor(penColor);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值