Home » Android » How to make custom brush for canvas in android?

How to make custom brush for canvas in android?

Posted by: admin April 23, 2020 Leave a comment

Questions:

In my canvas application i want to use custom brushes like brushes in attached image.so please somebody help me fast how can i make custom brushes like attached image?

In my app i made doted line using following code:

 mPaint.setPathEffect(new DashPathEffect(new float[] { 8, 8 }, 0));

and getting Blur and Emboss effect using following code:

 mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);

 mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);

enter image description here

How to&Answers:

As you can clearly see, no trivial shader effects / rectangles / circles can accomplish this.
Images / Bitmaps are used.

So simply repeatedly draw Bitmaps using canvas.drawBitmap. You draw the same Bitmap again and again while the finger moves.

For adding a custom color you can add a simple filter.

An Example

public class CanvasBrushDrawing extends View {
    private Bitmap mBitmapBrush;
    private Vector2 mBitmapBrushDimensions;

    private List<Vector2> mPositions = new ArrayList<Vector2>(100);

    private static final class Vector2 {
        public Vector2(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public final float x;
        public final float y;
    }

    public CanvasBrushDrawing(Context context) {
        super(context);

// load your brush here
        mBitmapBrush = BitmapFactory.decodeResource(context.getResources(), R.drawable.splatter_brush);
        mBitmapBrushDimensions = new Vector2(mBitmapBrush.getWidth(), mBitmapBrush.getHeight());

        setBackgroundColor(0xffffffff);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (Vector2 pos : mPositions) {
            canvas.drawBitmap(mBitmapBrush, pos.x, pos.y, null);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();
        switch (action) {
        case MotionEvent.ACTION_MOVE:
            final float posX = event.getX();
            final float posY = event.getY();
            mPositions.add(new Vector2(posX - mBitmapBrushDimensions.x / 2, posY - mBitmapBrushDimensions.y / 2));
            invalidate();
        }

        return true;
    }
}

Answer:

Though it is too late i want to share something. This might help someone. Various brush techniques are discussed in the following link with JavaScript code for HTML canvas. All you have to do is convert JavaScript code to your expected one. It is pretty simple to covert JavaScript Canvas code to Android Canvas code.

Exploring canvas drawing techniques

I have converted “Multiple lines” technique to Java code for android; You can check the following android view code.

public class MultipleLines extends View {

private Bitmap bitmap;
private Canvas canvas;

private Paint mPaint;

public MultipleLines(Context context) {
    super(context);
    init();
}

private void init(){
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0xFFFF0000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(1);
}

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

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

private boolean isDrawing;
private List<PointF> points = new ArrayList<>();

private void touch_start(float touchX, float touchY) {
    isDrawing = true;
    points.add(new PointF(touchX, touchY));

    canvas.save();
}
private void touch_move(float touchX, float touchY) {
    if (!isDrawing) return;

    canvas.drawColor(Color.TRANSPARENT);

    points.add(new PointF(touchX, touchY));

    stroke(offsetPoints(-10));
    stroke(offsetPoints(-5));
    stroke(points);
    stroke(offsetPoints(5));
    stroke(offsetPoints(10));
}

private void touch_up() {
    isDrawing = false;
    points.clear();
    canvas.restore();
}

private List<PointF> offsetPoints(float val) {
    List<PointF> offsetPoints = new ArrayList<>();
    for (int i = 0; i < points.size(); i++) {
        PointF point = points.get(i);
        offsetPoints.add(new PointF(point.x + val, point.y + val));
    }
    return offsetPoints;
}

private void stroke(List<PointF> points) {
    PointF p1 = points.get(0);
    PointF p2 = points.get(1);

    Path path = new Path();
    path.moveTo(p1.x, p1.y);

    for (int i = 1; i < points.size(); i++) {
        // we pick the point between pi+1 & pi+2 as the
        // end point and p1 as our control point
        PointF midPoint = midPointBtw(p1, p2);
        path.quadTo(p1.x, p1.y, midPoint.x, midPoint.y);
        p1 = points.get(i);
        if(i+1 < points.size()) p2 = points.get(i+1);
    }
    // Draw last line as a straight line while
    // we wait for the next point to be able to calculate
    // the bezier control point
    path.lineTo(p1.x, p1.y);

    canvas.drawPath(path,mPaint);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.WHITE);
    canvas.drawBitmap(bitmap, 0, 0, null);
}

private PointF midPointBtw(PointF p1, PointF p2) {
    return new PointF(p1.x + (p2.x - p1.x) / 2.0f, p1.y + (p2.y - p1.y) / 2.0f);
}

}