1. 程式人生 > >android canvas畫圖、塗鴉斷續

android canvas畫圖、塗鴉斷續

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;
    }

改進後畫圖的時候就不會出現斷斷續續的情況.