Daniel Daniel - 1 month ago 7
Android Question

How are you supposed to use a ShapeDrawable with a PathShape to draw a line on a custom View?

I am attempting to draw a line in a custom

View
. Here I've created a simple
Path
with just a single segment, created a
PathShape
from that, and finally stuck that into a
ShapeDrawable
with the intention of using that to draw on the
Canvas
inside
onDraw()
. However, this does not work. See my example, here.

package com.example.test;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.util.Log;
import android.view.View;

public class TestView extends View {

private Path mPath = null;
private Paint mPaint = null;
private PathShape mPathShape = null;
private ShapeDrawable mShapeDrawable = null;

public TestView(Context context) {
super(context);
}

private void init() {
int width = this.getWidth() / 2;
int height = this.getHeight() / 2;

Log.d("init", String.format("width: %d; height: %d", width, height));

this.mPath = new Path();
this.mPath.moveTo(0, 0);
this.mPath.lineTo(width, height);

this.mPaint = new Paint();
this.mPaint.setColor(Color.RED);

this.mPathShape = new PathShape(this.mPath, 1, 1);

this.mShapeDrawable = new ShapeDrawable(this.mPathShape);
this.mShapeDrawable.getPaint().set(this.mPaint);
this.mShapeDrawable.setBounds(0, 0, width, height);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);

// Doing this here because in the constructor we don't have the width and height of the view, yet
this.init();
}

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

Log.d("onDraw", "Drawing");

// This works, but won't let me do what I'm really trying to do
canvas.drawLine(0.0f, 0.0f, this.getWidth() / 2.0f, this.getHeight() / 2.0f, this.mPaint);

// This should work, but does not
//this.mPathShape.draw(canvas, this.mPaint);

// This should work, but does not
//this.mShapeDrawable.draw(canvas);
}

}


As you can see from my comments in the
onDraw()
method, neither using the
PathShape
nor the
ShapeDrawable
to draw the
Path
onto the
Canvas
actually works. Nothing is drawn when I try. Does anyone have any idea why?

The device I'm testing this on is running Android 4.1.1.

Answer

There are two issues with this.

The first is the Paint style. The default is Paint.Stroke.FILL, but with a line there's nothing to fill. I needed to add this (thanks, Romain Guy):

this.mPaint.setStyle(Paint.Style.STROKE);

The second issue is that the standard height and width in the PathShape is not correct. I had read the documentation on this, but did not understand it correctly. This became apparent once I fixed the first issue. Setting it to the height and width of my custom view (since I am drawing across the whole view) fixed this. I also had to change the bounds of the ShapeDrawable to match.

this.mPathShape = new PathShape(this.mPath, this.getWidth(), this.getHeight());

and

this.mShapeDrawable.setBounds(0, 0, this.getWidth(), this.getHeight());

Hopefully this helps someone else in the future.

Comments