Canvas.drawVertices (...) draws nothing

The following class is a view for a red triangle:

public class FreeStyleViewII extends View { private final Paint paint = new Paint(); private final int[] colors = new int[] { Color.RED, Color.RED, Color.RED, 0xFF000000, 0xFF000000, 0xFF000000 }; private final float[] verts = new float[] { 1f/2f * 200f, 1f/4f * 200f, 1f/4f * 200f, 3f/4f * 200f, 3f/4f * 200f, 3f/4f * 200f }; private final Path path = new Path(); { path.moveTo(1/2 * 200, 1/4 * 200); path.lineTo(1/4 * 200, 3/4 * 200); path.lineTo(3/4 * 200, 3/4 * 200); path.lineTo(1/2 * 200, 1/4 * 200); } private final RectF bounds = new RectF(); public FreeStyleViewII(Context context) { super(context); } public FreeStyleViewII(Context context, AttributeSet attrs) { super(context, attrs); } public FreeStyleViewII(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onDraw(Canvas canvas) { canvas.clipRect(bounds); canvas.drawRGB(0, 0, 0); paint.setStyle(Style.FILL); paint.setColor(Color.RED); // HERE. WHY DRAWVERTICES DOESN'T WORK BUT DRAWPATH DOES?... canvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, colors, 0, null, 0, 0, paint); // canvas.drawPath(path, paint); paint.setStyle(Style.STROKE); paint.setColor(Color.LTGRAY); canvas.drawLine(0, bounds.bottom / 2, bounds.right, bounds.bottom / 2, paint); canvas.drawLine(bounds.right / 2, 0, bounds.right / 2, bounds.bottom, paint); // Delay try { Thread.sleep(30); } catch (InterruptedException e) { } invalidate(); } @Override public void onSizeChanged(int w, int h, int oldW, int oldH) { bounds.set(1, 1, w - 1, h - 1); System.out.println(bounds.left + " " + bounds.top + " " + bounds.right + " " + bounds.bottom); verts[0] = bounds.left + ((bounds.right - bounds.left) * (1f / 2f)); verts[1] = bounds.top + ((bounds.bottom - bounds.top) * (1f / 4f)); System.out.println(" Point: X ----> " + verts[0] + " | Y ----> " + verts[1]); verts[2] = bounds.left + ((bounds.right - bounds.left) * (1f / 4f)); verts[3] = bounds.top + ((bounds.bottom - bounds.top) * (3f / 4f)); System.out.println(" Point: X ----> " + verts[2] + " | Y ----> " + verts[3]); verts[4] = bounds.left + ((bounds.right - bounds.left) * (3f / 4f)); verts[5] = bounds.top + ((bounds.bottom - bounds.top) * (3f / 4f)); System.out.println(" Point: X ----> " + verts[4] + " | Y ----> " + verts[5]); path.reset(); path.moveTo(verts[0], verts[1]); path.lineTo(verts[2], verts[3]); path.lineTo(verts[4], verts[5]); path.lineTo(verts[0], verts[1]); } } 

When I use the Canvas.drawPath method, it works fine. However, if I switch to Canvas.drawVertices, it does not draw anything. I checked what is said in Error in Canvas.drawVertices? (with the resulting code and logarithm) and the drawVertices () method did not draw anything on Android Canvas , but the result is the same in my case.

I am using AndroVM (v 4.1.1) in VirtualBox (v 4.1.22) for testing. Could it be an emulator?

Any idea?

+4
source share
1 answer

Short answer:

Disable hardware acceleration and everything will be fine!

Long answer:

I had the same problem. In my View View code, I have a Canvas.drawVertices () call that looks like this:

 canvas.drawVertices(Canvas.VertexMode.TRIANGLES, mTriVerts.length, mTriVerts, 0, null, 0, mTriangleColors, 0, null, 0, 0, mTriPaint); 

This works exactly the same as expected on many devices, but on my 4.x test device the triangle I'm trying to draw just disappears and there are no traces in the logarithm to indicate why.

After I didn’t find a solution with SO, I started digging around and accidentally found the following shocking solution: a bunch of standard material will not work if hardware acceleration is enabled, including any call to Canvas.drawVertices() , and hardware acceleration is turned on by default for all supporting it devices for Android 4.x and later.

The problem and a good solution are outlined in the official Android docs . To summarize it here, simply put this on the line preceding your unsupported calls:

 setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

This is at the View level, and, unfortunately, it is impossible to re-enable hardware acceleration in a view that has been set to program mode at the moment, but reading documents that, in his opinion, could be an option in the future. If you feel that your code needs hardware acceleration, just avoid using calls or collect incompatible code in the view yourself and project it to see that you are actually typing something, doing it this way.

IMPORTANT CHANGE:

The setLayerType() call is only supported at the level of Android 11 and later, which means that you must wrap your calls to this function in a version check for it to work in earlier versions, for example:

 if (android.os.Build.VERSION.SDK_INT >= 11) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } 

NOW, you must be tuned!

PS: I hope this answer reaches you on time!

+7
source

All Articles