Question

With my Android App I have a view that can be zoomed and panned. On that view I want to draw a line for the following points. But the path is not shown at all. I wonder if this has anything to do with the negative or large numbers in the list of points.

{"x":-317,"y":-744}, {"x":50,"y":-702}, {"x":394,"y":-663}, {"x":718,"y":-626}, {"x":1023,"y":-592}, {"x":1310,"y":-560}, {"x":1581,"y":-529}, {"x":1837,"y":-500}, {"x":2079,"y":-472}, {"x":2951,"y":198}, {"x":5997,"y":4780}, {"x":4064,"y":4143}, {"x":2686,"y":3689}, {"x":1654,"y":3348}, {"x":852,"y":3084}, {"x":211,"y":2873}, {"x":-312,"y":2700}, {"x":-748,"y":2556}, {"x":-895,"y":2213}, {"x":-574,"y":569}, {"x":-317,"y":-744}]}

Here's the code snippet.

private final Paint paintStrokeArea = new Paint(Paint.ANTI_ALIAS_FLAG);
private Point[] viewArea = ...

public MyView(Context context, AttributeSet attributeSet) {
    super(context, attributeSet);

    paintStrokeArea.setColor(Color.WHITE);
    paintStrokeArea.setStyle(Style.STROKE);
    paintStrokeArea.setStrokeWidth(4.5f);
    paintStrokeArea.setStrokeJoin(Join.MITER);
    paintStrokeArea.setPathEffect(null);
}

public onDraw(Canvas) {
    if (viewArea != null)
        renderViewArea(viewArea, canvas, paintStroke);
}

public static void renderViewArea(Point[] area, Canvas canvas, Paint paint) {
    if (area == null || canvas == null || paint == null)
        return;

    boolean first = true;
    Path path = new Path();
    Point last = new Point();

    for (Point current : area) {
        if (first) {
            first = false;
        } else {
            path.moveTo(last.x, last.y);
            path.lineTo(current.x, current.y);
        }

        last.set(current.x, current.y);
    }

    if (!first)
        canvas.drawPath(path, paint);
}
Was it helpful?

Solution

The same problem was described in this post. According to the answers, the problem occurs because drawPath is done in CPU by rendering it into a bitmap that is than transferred into the GPU. Because my path was too large, the bitmap could not be rendered (send to) the GPU. Better use drawLines because it uses the GPU directly. Here's a helper class that I encapsulated.

package eu.level12.tools;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;

/**
 * Provides several static methods for drawing onto Android's canvas.
 * Hardware-accelerated methods are named with the prefix render while others
 * begin with draw.
 * 
 * @author Matthias Heise
 * 
 */
public final class DrawingTools {

    /**
     * Draws the line specified by the given path using hardware-accelerated
     * method Canvas.drawLines. Has no effect if either argument is null or if
     * the line consists of less than two points.
     * 
     * @param path
     *            A path of points that specifies the line.
     * @param canvas
     *            The canvas onto which the line should be drawn.
     * @param paint
     *            The paint argument that specifies how the line is drawn.
     */
    public static void renderLine(Point[] path, Canvas canvas, Paint paint) {

        if (path == null || canvas == null || paint == null || path.length <= 1)
            return;

        final float[] lines = new float[(path.length - 1) * 4];
        int index = 0;
        final Point last = new Point();
        boolean first = true;

        for (Point current : path) {
            if (first) {
                first = false;
            } else {

                // start point
                lines[index] = last.x;
                lines[index + 1] = last.y;

                // end point
                lines[index + 2] = current.x;
                lines[index + 3] = current.y;

                index += 4;
            }

            last.set(current.x, current.y);
        }

        if (!first)
            canvas.drawLines(lines, paint);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top