自定义DottedLine视图绘制超长竖线遇纹理限制问题求解
嘿,这个问题我之前也碰到过,给你几个改动很小的解决方案,不用大拆大改你的现有代码:
解决方案
方案1:禁用该View的硬件加速(改动最小)
直接在你的DottedLine构造函数里加一行代码,强制使用软件渲染:
public DottedLine(Context context) { this(context, null); } public DottedLine(Context context, AttributeSet attrs) { super(context, attrs); // 这里保留你原来的paint初始化逻辑 setLayerType(LAYER_TYPE_SOFTWARE, null); // 关键代码 }
原理是:硬件加速会把View的渲染内容转换成OpenGL纹理,而纹理有尺寸上限;软件渲染不依赖OpenGL纹理,自然就不会触发这个警告。这个方案对你现有onDraw里的代码完全没有影响,只加一行就行,唯一的小缺点是软件渲染的性能略低于硬件加速,但如果你的这个虚线View不是特别复杂,基本感知不到差异。
方案2:用裁剪分块绘制(几乎不改动原有drawLine逻辑)
如果不想禁用硬件加速,那可以通过Canvas.clipRect()把长线条拆分成多个小区域绘制,每个区域的高度不超过纹理上限,而你的drawLine代码几乎不用改:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int maxTextureHeight = 4096; // 可以通过OpenGL API获取设备实际最大值,这里先硬编码示例 int startY = size; int endY = getHeight() - getHeight() % (size + gap); int totalHeight = endY - startY; // 如果线条长度没超过限制,正常绘制 if (totalHeight <= maxTextureHeight) { canvas.drawLine(getWidth() / 2, startY, getWidth() / 2, endY, paint); return; } // 分块裁剪绘制,每次只渲染一个小区域 int currentY = startY; while (currentY < endY) { int nextY = Math.min(currentY + maxTextureHeight, endY); canvas.save(); // 裁剪出当前要绘制的区域 canvas.clipRect(0, currentY, getWidth(), nextY); // 还是用你原来的drawLine代码,只会渲染裁剪区域内的部分 canvas.drawLine(getWidth() / 2, startY, getWidth() / 2, endY, paint); canvas.restore(); currentY = nextY; } }
这个方案的好处是保留了硬件加速,性能更好,而且你原来的drawLine逻辑完全保留,只是在外面加了个循环处理裁剪,改动非常有限。你甚至可以把分块的逻辑抽成一个工具方法,让onDraw更简洁。
额外提示:获取设备实际纹理上限
如果想更严谨一点,不要硬编码4096,可以通过OpenGL获取设备的实际最大纹理尺寸:
private int getMaxTextureSize() { int[] maxSize = new int[1]; GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0); return maxSize[0]; }
调用这个方法替换掉硬编码的maxTextureHeight即可,适配不同设备的限制。
内容的提问来源于stack exchange,提问作者GVillani82
相关产品推荐
相关产品推荐

