问题描述
下一个类是一个红色三角形的视图:
The next 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]);
}
}
当我使用 Canvas.drawPath 方法时,它工作正常.但是,如果我更改为 Canvas.drawVertices,它不会绘制任何内容.我已经检查了 Canvas.drawVertices 中的错误?(带有重现代码和 logcat) 和 方法 drawVertices()没有在 Android Canvas 上绘制任何东西,但在我的情况下结果是一样的.
When I use Canvas.drawPath method, it works fine. However, if I change to Canvas.drawVertices, it draws nothing. I have checked what is said in Bug in Canvas.drawVertices? (with repro code and logcat) and Method drawVertices() didn't drawing anything on Android Canvas, but the result is the same in my case.
我在 VirtualBox(v 4.1.22) 用于测试.会不会是模拟器?
I am using AndroVM(v 4.1.1) in VirtualBox(v 4.1.22) for testing. Could it be the emulator?
有什么想法吗?
推荐答案
简短回答:
禁用硬件加速,你会没事的!
Disable hardware acceleration and you will be fine!
长答案:
我遇到了完全相同的问题.在我的自定义视图代码中,我调用了 Canvas.drawVertices(),如下所示:
I had the exact same problem. In my custom View code, I have a call to Canvas.drawVertices() that looks like this:
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, mTriVerts.length, mTriVerts, 0, null, 0, mTriangleColors, 0, null, 0, 0, mTriPaint);
这在许多设备上的工作方式与预期完全一样,但在我的 4.x 测试设备上,我试图绘制的三角形消失了,并且 logcat 中没有任何迹象表明原因.
This works exactly like expected on many devices, but on my 4.x test device the triangle which I am trying to draw simply disappears, and there are no traces in the logcat to indicate as to why.
在 S.O. 没有找到解决方案之后我开始四处寻找,偶然发现了以下令人震惊的解决方案:如果启用硬件加速,包括对 Canvas.drawVertices()
的任何调用,并且硬件加速被打开,一堆标准的东西将不起作用默认情况下,在所有支持 Android 4.x 及更高版本的设备上都启用.
After not finding a solution at S.O. I started digging around and found by chance the following shocking solution: a bunch of standard stuff won't work if hardware acceleration is enabled, including any call to Canvas.drawVertices()
, and hardware acceleration is turned on by default on all devices that support it for Android 4.x and newer.
在官方 android 文档中概述了这个问题和一个好的解决方案.在这里总结一下,只需将其放在不受支持的呼叫之前:
The problem and a good solution is outlined in the official android docs. To summarize it here, just put this on the line preceeding your unsupported calls:
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
这是在 View
级别,很遗憾,目前无法在已设置为软件模式的视图上重新启用硬件加速,但阅读文档感觉就像那样可能是未来的一个选择.如果您觉得您的代码需要硬件加速,请避免使用这些调用,或者单独在视图中收集您不合规的代码,并对其进行分析以查看您通过这种方式实际上获得了什么.
This is on View
level, and it is unfortunately not possible to re-enable hardware acceleration on a view that has been set to software mode as of now, but reading the docs it felt like that might be an option in the future. If you feel your code needs hardware acceleration, simply avoid using the calls, or collect you non compliant code in a view by itself, and profile it to see that you are actually gaining something by doing it this way.
重要
setLayerType()
调用仅在 Android API 级别 11 及更高版本上受支持,这意味着您必须将对此函数的调用包装在版本检查中,以便它在早期版本上工作,如下所示:
The setLayerType()
call is only supported on Android API level 11 and later, that means you must wrap your calls to this function in a version check for it to work on earlier versions like this:
if (android.os.Build.VERSION.SDK_INT >= 11) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
现在你应该准备好了!
PS:希望这个答案能及时送达!
PS: I hope this answer reaches you in time!
这篇关于Canvas.drawVertices(...) 什么也不画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!