1

我在硬件加速活动 ( android:hardwareAccelerated="true") 中呈现长 TextView 时遇到问题。textview 没有背景颜色(即它是透明的)。当文本超过一定长度时,textview 会以纯黑色背景而不是透明背景呈现。

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);
}

但是,此代码对我不起作用。当满足条件时(文本太长),textview 变为 invisible。如果我尝试使用LAYER_TYPE_HARDWARE. (我尝试过,因为硬件加速指南说将图层类型设置为硬件以用于具有 alpha 的大视图。)

另外,我确实尝试过永久设置视图层类型。两种类型的结果略有不同:

  • LAYER_TYPE_SOFTWARE:当使用小于限制的文本创建活动时,它呈现良好。当添加文本超过限制时,视图会消失。当文本再次缩短到限制范围内时,它会重新出现。

  • LAYER_TYPE_HARDWARELAYER_TYPE_SOFTWARE与文本在太长后缩短时不会重新出现不同之外相同。必须重新创建活动才能使文本重新出现。

TL;博士

我遇到了由 OpenGL 限制引起的视图渲染问题,但view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);正在使视图消失而不是解决问题。

4

1 回答 1

0

稍微思考了一下这个问题,我意识到改变视图的图层类型并不能解决问题是有道理的。如果 Activity 是硬件加速的,则视图仍然必须存储在 GPU 纹理中才能呈现到屏幕上,而不管视图是否是硬件加速的。

为了解决这个问题,我只是降低了文本的分辨率(大小),直到视图的宽度小于GL_MAX_TEXTURE_SIZE. 这很有效,因为如果用户显示很多文本,则不需要高分辨率,因为他们会将其缩小以适应屏幕上的所有文本。

于 2013-06-05T19:33:22.683 回答