Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top