Android Paint:如何获得“喷枪”效果?

时间:2013-06-11 14:59:25

标签: java android graphics paint

我正在关注API演示中的“FingerPaint”演示。

我需要获得“喷枪”效果,因为当我在同一个地方画画时,它会变得更暗更暗。

请看图片:

因为你可以看到中心比较暗,因为我在同一个地方涂了多次油漆。

请问如何获得相同的效果,如果画了一次以上会变暗一点?

enter image description here

编辑编辑编辑

建议的

mPaint.setAlpha(0x80) 

有点工作,但只有当我松开触摸然后再次触摸时,如果我不释放并将手指放在屏幕上,则不会达到效果。

关键在于,如果不将手指从屏幕上松开,则无法达到效果,如果继续绘图而不释放触摸,则在涂漆时不会变暗。如果您松开触摸然后再次绘制,则会获得效果

这是我得到的结果。我不想要:

enter image description here

这将是理想的结果:

enter image description here


这是从API演示中获取的代码:

public class FingerPaint extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new MyView(this));

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0x44FF0000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(12);

}

private Paint mPaint;

public class MyView extends View {

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;

    public MyView(Context c) {
        super(c);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFAAAAAA);

        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touch_move(float x, float y) {
        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;
        }
    }

    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up();
            invalidate();
            break;
        }
        return true;
    }
}

}

3 个答案:

答案 0 :(得分:5)

我的代码中只做了一些小改动。

 mPaint.setColor(Color.BLACK);// changed color to balck
 mPaint.setAlpha(0x80); // only change    

活动类

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new MyView(this));

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setAlpha(0x80); // only change
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(12);

}

private Paint mPaint;

public class MyView extends View {

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;

    public MyView(Context c) {
        super(c);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFAAAAAA);

        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touch_move(float x, float y) {
        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;
        }
    }

    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up();
            invalidate();
            break;
        }
        return true;
    }
}

}
快照

enter image description here

答案 1 :(得分:4)

这种方法更像是像Photoshop一样的模拟方法:沿着路径集成并绘制单个油漆飞溅,其间的间距可调。

enter image description here

public class DrawView extends View {
public Paint mPaint;

private Bitmap mBitmap;
private Canvas mCanvas;

private int strokeRadius;
private ShapeDrawable mBrush;
private Paint mBitmapPaint;

private float mPreviousX, mPreviousY;

public DrawView(Context context, AttributeSet attrs) {
    super( context,  attrs);

    mBitmapPaint = new Paint(Paint.DITHER_FLAG);

    int strokeWidth = 20;

    strokeRadius = strokeWidth/2;

    Shape brushShape = new OvalShape();

    mBrush = new ShapeDrawable(brushShape);

    Paint paint = mBrush.getPaint();

    // radial gradient shader with a transparency falloff, if you don't want this,
    // just set a color on the paint and remove the setShader call
    Shader shader = new RadialGradient(strokeRadius, strokeRadius, strokeRadius,
            Color.argb(255, 0, 0, 0), Color.argb(0, 0, 0, 0), Shader.TileMode.CLAMP);

    paint.setShader(shader);
    paint.setAlpha(0x10);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(0xFF00B8F5);

    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}

private void touch_start(float x, float y) {
    mPreviousX = x;
    mPreviousY = y;
}

private void touch_move(MotionEvent event)
{
    float x = event.getX();
    float y = event.getY();

    // get vector from previous to current position
    float xdist = x - mPreviousX;
    float ydist = y - 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. The end point will be drawn by the start point of the
    // next stroke, or by the touch_up method. If we drew both the start and
    // end point there it would be doubled up
    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);
    }

    // update the previous position
    mPreviousX = x;
    mPreviousY = y;
}

private void touch_up(MotionEvent event) {
    drawSplash((int) event.getX(), (int)event.getY());
}

/**
 * draws the brush to the canvas, centered around x and y
 * @param x
 * @param y
 */
private void drawSplash(int x, int y)
{
    mBrush.setBounds(x - strokeRadius, y - strokeRadius, x + strokeRadius, y + strokeRadius);

    mBrush.draw(mCanvas);

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(event);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up(event);
        invalidate();
        break;
    }
    return true;
}
}

编辑:快照(Raghunandan)。使用白色背景和黑色涂料进行结果测试。

enter image description here

答案 2 :(得分:2)

找到解决方案。 对于那些可能感兴趣的人:

public class DrawView extends View {
public Paint mPaint;
private Paint mPaint1;
private Paint mPaint2;

private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;

public DrawView(Context context, AttributeSet attrs) {
    super( context,  attrs);

    mPath = new Path();
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    mPaint = new Paint();
    mPaint.setAlpha(0x80);
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0x44000000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.BUTT);
    mPaint.setStrokeWidth(5);

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);

}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(0xFF00B8F5);

    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    //mCanvas.drawPoint(x, y, mPaint);

}

private void touch_move(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    Path npath=new Path();
    npath.moveTo(mX, mY);
    npath.lineTo( x ,y );
    mX=x;
    mY=y;
    mCanvas.drawPath(npath, mPaint);
    npath.reset();
    //Log.e("","sto disegando");
}

private void touch_up() {

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(event);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up();
        invalidate();
        break;
    }
    return true;
}
}

编辑:附加我的模拟器(Raghunandan)的快照。我使用你的代码没有变化,除了增加笔画宽度,它看起来像下面。

慢慢画画时效果不佳。

enter image description here

如果你绘制一条严格的线条没有问题,屏幕截图的行程宽度为12。但是当你绘制曲折时,你可以看到它看起来不太好

enter image description here