带有LAYER_TYPE_HARDWARE或LAYER_TYPE_SOFTWARE不可见的长文本TextView

时间:2013-06-04 19:50:41

标签: android view textview android-ui hardware-acceleration

我在硬件加速活动(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_SIZE OpenGL参数并将其与width进行比较。果然,问题发生在width > GL_MAX_TEXTURE_SIZE

为了解决这个问题,我在文本太长的时候给disable hardware acceleration on the view写了一些代码:

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,也会发生这种情况。 (我试过这个,因为the Hardware Acceleration guide说要为包含alpha的大型视图设置图层类型为HARDWARE。)

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

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

  • LAYER_TYPE_HARDWARE:与LAYER_TYPE_SOFTWARE相同,但文字在太长时间缩短后不会重新出现。必须重新创建活动才能重新显示文本。

TL; DR

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

1 个答案:

答案 0 :(得分:0)

在考虑了这个问题之后,我意识到改变视图的图层类型并不能解决问题。如果活动是硬件加速的,则无论视图是否是硬件加速,视图仍然必须存储在GPU纹理中以呈现到屏幕上。

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