# Android中怎么利用SurfaceView顯示Camera圖像
## 一、SurfaceView與Camera概述
在Android應用開發中,實時顯示攝像頭圖像是常見需求。`SurfaceView`作為專門用于高效繪制動態內容的視圖組件,配合`Camera` API可以實現這一功能。其核心優勢在于:
1. **獨立繪制線程**:SurfaceView擁有獨立的Surface,可在非UI線程渲染
2. **雙緩沖機制**:減少畫面閃爍
3. **硬件加速支持**:適合視頻/3D等高性能場景
## 二、實現步驟詳解
### 1. 添加權限和特性聲明
```xml
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<!-- 適配Android 9+ -->
<uses-permission android:name="android.permission.RECORD_AUDIO"
android:required="false" />
<SurfaceView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
public class CameraActivity extends AppCompatActivity
implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
mSurfaceView = findViewById(R.id.camera_preview);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
// 設置Surface類型
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// 打開后置攝像頭
mCamera = Camera.open();
// 設置預覽方向(解決畫面旋轉問題)
mCamera.setDisplayOrientation(90);
// 綁定SurfaceView
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.e("Camera", "Error setting preview: " + e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Surface尺寸變化時重新設置參數
if (mHolder.getSurface() == null) return;
try {
mCamera.stopPreview();
Camera.Parameters params = mCamera.getParameters();
// 設置預覽尺寸(需選擇設備支持的尺寸)
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
Camera.Size optimalSize = getOptimalSize(sizes, width, height);
params.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(params);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.e("Camera", "Error restarting preview: " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
private Camera.Size getOptimalSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
double diff = Math.abs(size.height - h) + Math.abs(size.width - w);
if (diff < minDiff) {
optimalSize = size;
minDiff = diff;
}
}
return optimalSize != null ? optimalSize : sizes.get(sizes.size() - 1);
}
權限處理:Android 6.0+需要運行時權限申請
if (checkSelfPermission(Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, 100);
}
方向適配:不同設備可能需要特殊處理預覽方向
新API遷移:Android 5.0+建議使用Camera2
API,但SurfaceView仍適用
性能優化:
TextureView
替代SurfaceView
可實現動畫效果SurfaceTexture
進行更靈活的圖像處理通過上述實現,開發者可以構建基礎的相機預覽功能,后續可擴展添加拍照、濾鏡等高級功能。 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。