android canvas畫圖、塗鴉斷續
阿新 • • 發佈:2019-01-05
用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;
}
改進後畫圖的時候就不會出現斷斷續續的情況.