用mCanvas.drawLine
方法画出来的线可能会断断续续,原因是onTouchEvent中的move方法并不是每个点都调用的,所以需要在点没有调用方法的时候让两点之间生成二次贝塞尔曲线
改进前代码:
private void initDraw() {
mIvMode1Anim.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onTouch: ==================ACTION_DOWN==================");
//创建画纸
if (mBitmap == null) {
mBitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
//创建画布
mCanvas = new Canvas(mBitmap);
//将背景设置为透明
mCanvas.drawColor(Color.WHITE);
//创建画笔
mPaint = new Paint();
mPaint.setColor(Color.BLACK);//画笔的颜色
mPaint.setStrokeWidth(20);//画笔的粗细
}
//获取坐标
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "onTouch: ==================ACTION_MOVE==================");
mCurrentX = event.getX();
mCurrentY = event.getY();
//绘制直线
mCanvas.drawLine(mStartX, mStartY, mCurrentX, mCurrentY, mPaint);
//第二条线的起始点,就是上一条的重点
mStartX = mCurrentX;
mStartY = mCurrentY;
//将bitmap展示到界面
mIvMode1Anim.setImageBitmap(mBitmap);
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "onTouch: ==================ACTION_UP==================");
break;
}
//返回true代表了消费了这个事件,那么down后面的move和up事件才能进来
//返回false,代表不消费这个事件,那么down后面的move和up就进不来
return true;
}
});
}
改进后代码:
private Paint mPaint;
private Path mPath;
private float mX;
private float mY;
private float[] mDownPoint = new float[2];
private float[] mUpPoint = new float[2];
private DrawCallBack mBack;
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
mPaint = new Paint();
mPath = new Path();
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(20);
mPaint.setColor(Color.BLACK);
// 抗锯齿
mPaint.setAntiAlias(true);
// 防抖动
mPaint.setDither(true);
}
public void setCallBack(DrawCallBack callBack) {
this.mBack = callBack;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
//手指点下屏幕时调用
private void touchDown(MotionEvent event) {
//mPath.rewind();
//重置绘制路线,即隐藏之前绘制的轨迹
mPath.reset();
float x = event.getX();
float y = event.getY();
mX = x;
mY = y;
//mPath绘制的绘制起点
mPath.moveTo(x, y);
}
//手指在屏幕上滑动时调用
private void touchMove(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final float previousX = mX;
final float previousY = mY;
final float dx = Math.abs(x - previousX);
final float dy = Math.abs(y - previousY);
//两点之间的距离大于等于3时,生成贝塞尔绘制曲线
if (dx >= 3 || dy >= 3) {
//设置贝塞尔曲线的操作点为起点和终点的一半
float cX = (x + previousX) / 2;
float cY = (y + previousY) / 2;
//二次贝塞尔,实现平滑曲线;previousX, previousY为操作点,cX, cY为终点
mPath.quadTo(previousX, previousY, cX, cY);
//mPath.lineTo(x, y);
//第二次执行时,第一次结束调用的坐标值将作为第二次调用的初始坐标值
mX = x;
mY = y;
}
}
public void resetView() {
mPath.reset();
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownPoint[0] = event.getX();
mDownPoint[1] = event.getY();
touchDown(event);
break;
case MotionEvent.ACTION_MOVE:
touchMove(event);
break;
case MotionEvent.ACTION_UP:
mUpPoint[0] = event.getX();
mUpPoint[1] = event.getY();
if (mBack != null) {
mBack.drawCompose(mDownPoint, mUpPoint);
}
//mPath.reset();
//postInvalidate();
//
//isError();
break;
default:
break;
}
invalidate();
return true;
}
改进后画图的时候就不会出现断断续续的情况.