画应用。 2喷涂类型,SolidLine和喷枪,喷枪绘制到mCanvas,只有在选中时才能看到实线

时间:2014-03-25 18:45:26

标签: android android-canvas ondraw

默认为SolidLine,我可以开始绘图,切换到Airbrush,一切看起来都很好。如果我切换回SolidLine,喷枪绘制消失,但之前的SolidLine绘制仍然存在。如果我然后切换回喷枪,之前的喷枪绘图重新出现,之前的SolidLine绘图仍然存在。在功能 touch_up(event),in(line_type == SOLID_LINE),如果我注释掉

// mCanvas.drawPath(mPath,mPaint);

然后当我选择Airbrush时,SolidLine绘制消失,当我选择回SolidLine时重新开始,而通常Airbrush绘图消失。所以我似乎很清楚我需要让我的Airbrush绘制到onDraw Canvas上,但是我还没有能够让它工作,尝试各种各样的事情,专注于尝试绘制用于初始化的Bitmap mSourceBM mCanvas,放在onDraw Canvas画布上。

任何想法都将不胜感激!

我的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);
    }
}

我的初始化函数,用于上下文

    private void init(AttributeSet attrs, int defStyle) {
    if(line_type == SOLID_LINE){
        setSolidLine(); // various paint settings
    }else if(line_type == AIRBRUSH){
        setAirbrush(); // other paint settings
    }
}

这是在touch_move中多次触发的drawSpalsh函数,以及一次触摸。它绘制一个具有径向渐变和半径的涂料 点(x,y)处的Paint Stroke宽度的一半。调用invalidate() 每次touch_move(x,y),touch_start(x,y)和touch_up(事件)后的onTouchEvent 调用

    private void drawSplash(int x, int y)
{   
    mBrush.setBounds(x - strokeRadius, y - strokeRadius, x + strokeRadius, y + strokeRadius);
    mBrush.draw(mCanvas);
    //mPaint = mBrush.getPaint();
    //mCanvas.drawBitmap(mSourceBM, x, y, mPaint);

    //mCanvas.drawPaint(mPaint);
}

touch_start,从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");
    }
}

从onTouchEvent调用touch_move

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

从onTouchEvent调用touch_up

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

活动设置位图。实际上我没有使用BitmapDrawable。只是 用于初始化Airbrush canvas mCanvas的位图。

    /**
 * Sets the Canvas Bitmap we intend to modify
 */
public boolean setCanvasBitmapDrawable(BitmapDrawable bitmapdrawable, Bitmap sourceBM, int left_bound, int top_bound) {
    // supply bounds as parameters
    mSourceBM = sourceBM;
    // mSourceBM = convertToMutable(this, mSourceBM);

    bmDrawable = bitmapdrawable;
    mCanvas = new Canvas(mSourceBM);
    //bmDrawable.setBounds(left_bound, top_bound, bitmapdrawable.getIntrinsicWidth()+left_bound, bitmapdrawable.getIntrinsicHeight()+top_bound);

    invalidate();
    return true;
}

1 个答案:

答案 0 :(得分:0)

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

上述声明中的ifs只能绘制一个或另一个。将它们从提取中取出,ontouch中的if语句就足以显示您使用的类型,并且它应该可以正常工作