5

次のクラスは、赤い三角形のビューです。

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 で何も描画しませんでしたが、私の場合、結果は同じです。

テスト用にVirtualBox(v 4.1.22)でAndroVM(v 4.1.1)を使用しています。それはエミュレータでしょうか?

何か案が?

4

1 に答える 1

10

簡潔な答え:

ハードウェア アクセラレーションを無効にすれば問題ありません。

長い答え:

私はまったく同じ問題を抱えていました。私のカスタム View コードでは、次のような Canvas.drawVertices() への呼び出しがあります。

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

これは多くのデバイスで期待どおりに機能しますが、私の 4.x テスト デバイスでは、描画しようとしている三角形が消えてしまい、その理由を示すトレースが logcat にありません。

SO で解決策が見つからなかった後、掘り下げ始めたところ、偶然、次の衝撃的な解決策を見つけました。 への呼び出しを含め、ハードウェア アクセラレーションが有効になっている場合、多くの標準的なものは機能しませんCanvas.drawVertices()。 Android 4.x 以降でサポートされているデバイス。

問題と適切な解決策は、公式の Android ドキュメント で概説されています。ここで要約すると、サポートされていない呼び出しの前の行にこれを入れてください:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

これはViewレベルであり、残念ながら現在のところソフトウェア モードに設定されているビューでハードウェア アクセラレーションを再度有効にすることはできませんが、ドキュメントを読むと、将来的にはオプションになる可能性があるように感じました。コードにハードウェア アクセラレーションが必要だと思われる場合は、呼び出しを使用しないようにするか、準拠していないコードを単独でビューに収集し、プロファイリングして、この方法で実際に何かを得ていることを確認してください。

重要な編集:

このsetLayerType()呼び出しは Android API レベル 11 以降でのみサポートされています。つまり、この関数の呼び出しをバージョン チェックでラップして、以前のバージョンで機能させる必要があります。

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

これで準備完了です!

PS:この回答が間に合うことを願っています!

于 2013-04-27T21:37:26.850 に答える