使用GlSurfaceView时CameraX预览随设备侧倾出现扭曲问题求助
问题分析与解决方案
核心原因
设备倾斜时,CameraX会根据姿态调整画面输出的裁剪/变换矩阵,但GlSurfaceView的SurfaceTexture不会自动同步这些参数,加上相机输出比例与GlSurfaceView显示比例的不匹配叠加,最终导致纹理映射时出现拉伸扭曲,且倾斜角度越大扭曲越明显。
具体修复步骤
1. 同步CameraX的变换矩阵到OpenGLES
CameraX的Preview用例会输出画面的变换信息,必须把这些矩阵传递给Renderer来修正纹理坐标映射:
- 设置Preview时,监听输出更新并获取变换矩阵:
preview.setSurfaceProvider(yourSurfaceProvider) preview.setOnPreviewOutputUpdateListener { output -> val transformMatrix = output.textureTransformMatrix // 通过全局变量或接口把矩阵传给Renderer yourRenderer.updateTextureTransform(transformMatrix) }
- 在Renderer的
onDrawFrame中,将该矩阵应用到纹理坐标计算,替换默认的纹理映射矩阵。
2. 动态匹配SurfaceTexture缓冲区尺寸
禁止硬编码缓冲区大小,严格对齐CameraX的输出画面尺寸:
- 在Preview输出更新回调中,动态设置
SurfaceTexture的缓冲区参数:
Size outputSize = output.getSize(); surfaceTexture.setDefaultBufferSize(outputSize.getWidth(), outputSize.getHeight());
3. 修正GlSurfaceView的显示比例
避免View被拉伸变形,确保其宽高比与相机输出一致:
- XML布局中开启比例适配:
<android.opengl.GLSurfaceView android:id="@+id/gl_surface_view" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true"/>
- 代码中绑定相机后,同步相机的目标比例:
val cameraInfo = cameraProvider.bindToLifecycle(this, cameraSelector, preview) val aspectRatio = cameraInfo.cameraInfo.targetAspectRatio glSurfaceView.setAspectRatio(aspectRatio)
4. 补偿设备倾斜的姿态变换
若仍有残留扭曲,结合加速度传感器获取倾斜角度,调整OpenGLES投影矩阵:
- 注册传感器监听获取倾斜角度:
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
- 在顶点着色器中加入旋转矩阵抵消倾斜影响:
mat4 tiltRotation = rotate(tiltAngle, 0.0, 0.0, 1.0); gl_Position = projectionMatrix * tiltRotation * modelViewMatrix * vec4(position, 1.0);
验证流程
- 先修复矩阵同步和缓冲区尺寸问题,测试倾斜扭曲是否缓解;
- 若问题残留,加入姿态补偿的投影矩阵调整;
- 对比
PreviewView的输出,确保GlSurfaceView的画面比例、变换完全对齐。
内容的提问来源于stack exchange,提问作者Aprog
相关产品推荐
相关产品推荐

