1

ハードウェア アクセラレーション アクティビティ ( ) で長い TextView をレンダリングする際に問題が発生していますandroid:hardwareAccelerated="true"。テキストビューには背景色がありません (つまり、透明です)。テキストが特定の長さよりも長い場合、テキストビューは透明な背景ではなく黒一色の背景でレンダリングされます。

TextView 内のテキストはユーザーが編集でき、実際の改行を除いて折り返されないように強制されています。私は次のようにテキストの幅を計算することでこれを行っています:

int textWidth = 0;
String[] lines = string.split("\\n");
for (String line : lines) {
    int lineWidth = (int) tv.getPaint().measureText(line);
    if (lineWidth > textWidth) {
        textWidth = lineWidth;
    }
}
int width = m.getPaddingLeft() + tv.getPaddingLeft() + textWidth
            + tv.getPaddingRight() + m.getPaddingRight();

次に、ViewGroup の onMeasure メソッドをオーバーライドして、幅を少なくともテキストと同じ長さにします。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int newWidth = Math.max(getMeasuredWidth(), width);
    setMeasuredDimension(newWidth, getMeasuredHeight());
}

これはすべて期待どおりに機能していますが、テキストが非常に大きくなる可能性があります-明らかに大きすぎます.

試行された解決策: 問題は、OpenGL がそれほど長いものをレンダリングできないことにあると推測したので、GL_MAX_TEXTURE_SIZEOpenGL パラメーターを照会し、それをwidth. 案の定、問題が発生するのはwidth > GL_MAX_TEXTURE_SIZE.

この問題を解決するために、テキストが長すぎる場合にビューでハードウェア アクセラレーションを無効にするコードをいくつか書きました。

int[] maxGlTexSize = new int[1];
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxGlTexSize, 0);
if (width > maxGlTexSize[0]) {
    Log.e("Debug", "Too big for GL");
    tv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} else {
    Log.i("Debug", "Small enough for GL");
    tv.setLayerType(View.LAYER_TYPE_NONE, null);
}

ただし、このコードは機能しません。条件が満たされる (テキストが長すぎる) 場合、テキストビューは非表示になります。これは、 を使用しようとした場合にも発生しますLAYER_TYPE_HARDWARE(ハードウェア アクセラレーション ガイドでは、アルファ付きの大きなビューではレイヤー タイプを HARDWARE に設定するように指示されているため、それを試しました。)

また、ビューレイヤータイプを永続的に設定しようとしました。結果は、2 つのタイプでわずかに異なっていました。

  • LAYER_TYPE_SOFTWARE: 制限より小さいテキストでアクティビティを作成すると、正常にレンダリングされます。制限を超えてテキストを追加すると、ビューが消えます。テキストが再び制限内に収まるように短縮されると、再び表示されます。

  • LAYER_TYPE_HARDWARELAYER_TYPE_SOFTWARE:テキストが長すぎた後に短縮されたときに再表示されないことを除いて、 と同じです。テキストを再表示するには、アクティビティを再作成する必要があります。

TL;DR

OpenGL の制限が原因でビューのレンダリングに問題がview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);ありますが、問題を解決するのではなく、ビューを非表示にしています。

4

1 に答える 1

0

この問題について少し考えた後、ビューのレイヤー タイプを変更しても問題が解決しないのは理にかなっていることに気付きました。アクティビティがハードウェア アクセラレーションの場合、ビューがハードウェア アクセラレーションであるかどうかに関係なく、ビューを GPU テクスチャに格納して画面にレンダリングする必要があります。

この問題を解決するために、ビューの幅がGL_MAX_TEXTURE_SIZE. これはうまく機能します。なぜなら、ユーザーがテキストを大量に表示する場合、テキストを高解像度にする必要がないからです。これは、画面上のすべてのテキストに合わせてテキストを縮小するためです。

于 2013-06-05T19:33:22.683 に答える