Android GLSurfaceView 清屏问题
Android GLSurfaceView 清屏问题
编写了一个通过 GLSurfaceView 渲染视频画面的逻辑,但是发现移除之后会残留最后一帧,排查了一天终于找到了问题。
先说结论,只要管理好他的生命周期,系统会处理好清屏,不会发生残留。
由于问题太傻逼,先卖个关子,问题的原因在最后面。下面是网上找的不太行的方法:
1
2
3
4
5
public void onDrawFrame(GL10 gl) {
// 清屏逻辑:仅绘制背景,无法做到透明
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
的确能清屏,但是做不到透明,我的目标是移除之后原本父视图是什么颜色就还是什么颜色,这个逻辑实际上是将 GLSurfaceView 显示区域清理成黑色了。
又尝试通过启用混合模式清理成透明的,测试后没有任何效果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 配置OpenGL版本(这里使用ES 2.0)
setEGLContextClientVersion(2);
setEGLContextFactory(createContextFactory());
// 关键:配置EGL支持8位Alpha通道
setEGLConfigChooser(8, 8, 8, 8, 16, 0); // R(8), G(8), B(8), A(8), 深度缓冲16位
// 设置Surface为透明格式
getHolder().setFormat(PixelFormat.TRANSLUCENT);
// 视图自身背景设为透明
setBackgroundColor(Color.TRANSPARENT);
public void onDrawFrame(GL10 gl) {
// 启用混合模式,允许透明叠加
// GLES20.glEnable(GLES20.GL_BLEND);
// GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
// 清屏逻辑:仅绘制背景,无法做到透明
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
还可以通过 Canvas 清屏,也不行
1
2
3
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint);
揭晓答案
最后发现虽然我置空了对象,但是他还躺在父视图上,因为移除的逻辑写错了,是我没有掌握好安卓的 removeView 方法,默认情况下直接调用实际上是省略了 this ,意思是从当前视图上移除传入参数的子视图,可恰巧我这个 GLSurfaceView 对象不是当前视图的子视图,所以误认为移除了,但实际还在那里。
1
2
3
4
5
ViewGroup parent = (ViewGroup) uiView.getParent();
if (parent != null) {
- removeView(uiView);
+ parent.removeView(uiView);
}
这个方法感觉很难用,iOS 里有个 removeFromSuperView 的方法很好用。
本文由作者按照 CC BY 4.0 进行授权