Android 绘画应用程序。2种绘制类型,实线和喷枪,喷枪绘制到mCanvas,仅在选中实线时才能看到它

Android 绘画应用程序。2种绘制类型,实线和喷枪,喷枪绘制到mCanvas,仅在选中实线时才能看到它,android,android-canvas,ondraw,Android,Android Canvas,Ondraw,默认为实线,我可以开始画图,切换到喷枪,一切看起来都很好。如果切换回实线,喷枪绘制将消失,但之前的实线绘制将保留。如果随后切换回喷枪,则上一次喷枪绘制将重新出现,而上一次实线绘制将保留。在函数中 如果我注释掉,触摸事件,行内类型==实线 //mCanvas.drawPathmPath,mPaint 然后,当我选择“喷枪”时,实线绘制消失,当我选择“返回到实线”时重新绘制,而像往常一样,喷枪绘制消失。因此,我似乎很清楚,我需要在onDraw画布上绘制我的喷枪,但我一直无法使其正常工作,我尝试了各种

默认为实线,我可以开始画图,切换到喷枪,一切看起来都很好。如果切换回实线,喷枪绘制将消失,但之前的实线绘制将保留。如果随后切换回喷枪,则上一次喷枪绘制将重新出现,而上一次实线绘制将保留。在函数中 如果我注释掉,触摸事件,行内类型==实线

//mCanvas.drawPathmPath,mPaint

然后,当我选择“喷枪”时,实线绘制消失,当我选择“返回到实线”时重新绘制,而像往常一样,喷枪绘制消失。因此,我似乎很清楚,我需要在onDraw画布上绘制我的喷枪,但我一直无法使其正常工作,我尝试了各种方法,重点是尝试在onDraw画布上绘制用于初始化mCanvas的位图mSourceBM

任何想法都将不胜感激

我的onDraw函数

    @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if(line_type == SOLID_LINE){
        for (Pair<Path, Paint> p : paths) {
            canvas.drawPath(p.first, p.second);
        }
        canvas.drawPath(mPath, mPaint);
    }else if(line_type == AIRBRUSH){
        Log.d(DTAG, "onDraw: AIRBRUSH: no call");
        canvas.drawBitmap(mSourceBM, 0,0, null);
    }
}
这里是drawSpalsh函数,在touch_move中触发多次,在touch up中触发一次。它绘制具有径向渐变和半径为的绘制 点x、y处绘制笔划宽度的一半。无效被调用 每次触屏移动X、y、触屏开始TX、y和触屏事件后的onTouchEvent 打电话

触摸启动,从onTouchEvent调用

    private void touch_start(float x, float y) {
    if(line_type == SOLID_LINE){
        undonePaths.clear();// we clear the undonePaths because we are drawing
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }else if(line_type == AIRBRUSH){
        mPreviousX = x;
        mPreviousY = y;
        Log.d(DTAG, "touch_start");
    }
}
private void touch_move(float x, float y) {
    if(line_type == SOLID_LINE){
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
        // displayMemoryUsage("touch_move SOLID");
    }else if(line_type == AIRBRUSH){
        float mX = x;
        float mY = y;

        // get vector from previous to current position
        float xdist = mX - mPreviousX;
        float ydist = mY - mPreviousY;

        // get the length
        float segmentLength = (float) Math.sqrt(xdist * xdist + ydist * ydist);

        // derive a suitable step size from stroke width
        float stepSize = Math.max(strokeRadius / 10, 1f);

        // calculate the number of steps we need to take
        // NOTE: this draws a bunch of evenly spaced splashes from the start point
        // to JUST BEFORE the end point.
        int steps = Math.max(Math.round(segmentLength / stepSize), 2); 
        for(int i = 0; i < steps; ++i)
        {
            int currentX = (int) (mPreviousX + xdist * i / steps);
            int currentY = (int) (mPreviousY + ydist * i / steps);

            drawSplash(currentX, currentY);
        }
        //Log.d(DTAG, "touch_move: AIRBRUSH xdist, ydist: "+xdist+" "+ydist);
        // update the previous position
        mPreviousX = mX;
        mPreviousY = mY;
        //displayMemoryUsage("touch_move AIR");
        //Log.d(DTAG, "touch_move AIR: previous x y "+mX+" "+mY);
    }
}
    private void touch_up(MotionEvent event) {
    if(line_type == SOLID_LINE){
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        Paint newPaint = new Paint(mPaint);
        paths.add(new Pair<Path, Paint>(mPath, newPaint));
        mPath = new Path();
    }else if(line_type == AIRBRUSH){
        drawSplash((int) event.getX(), (int)event.getY());
    }
}
从onTouchEvent调用touch_move

    private void touch_start(float x, float y) {
    if(line_type == SOLID_LINE){
        undonePaths.clear();// we clear the undonePaths because we are drawing
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }else if(line_type == AIRBRUSH){
        mPreviousX = x;
        mPreviousY = y;
        Log.d(DTAG, "touch_start");
    }
}
private void touch_move(float x, float y) {
    if(line_type == SOLID_LINE){
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
        // displayMemoryUsage("touch_move SOLID");
    }else if(line_type == AIRBRUSH){
        float mX = x;
        float mY = y;

        // get vector from previous to current position
        float xdist = mX - mPreviousX;
        float ydist = mY - mPreviousY;

        // get the length
        float segmentLength = (float) Math.sqrt(xdist * xdist + ydist * ydist);

        // derive a suitable step size from stroke width
        float stepSize = Math.max(strokeRadius / 10, 1f);

        // calculate the number of steps we need to take
        // NOTE: this draws a bunch of evenly spaced splashes from the start point
        // to JUST BEFORE the end point.
        int steps = Math.max(Math.round(segmentLength / stepSize), 2); 
        for(int i = 0; i < steps; ++i)
        {
            int currentX = (int) (mPreviousX + xdist * i / steps);
            int currentY = (int) (mPreviousY + ydist * i / steps);

            drawSplash(currentX, currentY);
        }
        //Log.d(DTAG, "touch_move: AIRBRUSH xdist, ydist: "+xdist+" "+ydist);
        // update the previous position
        mPreviousX = mX;
        mPreviousY = mY;
        //displayMemoryUsage("touch_move AIR");
        //Log.d(DTAG, "touch_move AIR: previous x y "+mX+" "+mY);
    }
}
    private void touch_up(MotionEvent event) {
    if(line_type == SOLID_LINE){
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        Paint newPaint = new Paint(mPaint);
        paths.add(new Pair<Path, Paint>(mPath, newPaint));
        mPath = new Path();
    }else if(line_type == AIRBRUSH){
        drawSplash((int) event.getX(), (int)event.getY());
    }
}

上述语句中的ifs使其仅绘制一个或另一个。将它们从ondraw中删除,ontouch中的if语句将足以显示您使用的是哪种类型,并且应该可以正常工作

谢谢。SolidLine不绘制任何内容,若elses注释掉,它只绘制喷枪,但选择SolidLine时喷枪仍保留。这是一个我没有研究过的方向。感谢@La5t5tarfighter的快速响应,我会进一步调查的。明白了。在保持if和抛弃else的同时尝试它!不,不!你第一次就有了!我已经注释掉了mCanvas.drawPathmPath,mPaint;保持联系!忘了!非常感谢。真不敢相信我的头撞了这么久!非常感谢。
   @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

        for (Pair<Path, Paint> p : paths) {
            canvas.drawPath(p.first, p.second);
        }
        canvas.drawPath(mPath, mPaint);

        Log.d(DTAG, "onDraw: AIRBRUSH: no call");
        canvas.drawBitmap(mSourceBM, 0,0, null);
    }