SurfaceView 的裁剪相机预览

Crop camera preview for SurfaceView

我有一个用于条形码扫描的 SurfaceView(来自 this tutorial)。

<SurfaceView
        android:id="@+id/camera_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone" />

需要设置屏幕高度为 1/4 的裁剪相机预览。

我根据屏幕尺寸设置了视图尺寸:

cameraView = (SurfaceView) findViewById(R.id.camera_view);

final DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels / 4);
        cameraView.setLayoutParams(layoutParams);

但是相机预览只是缩小了!

我是这样设置的

final BarcodeDetector barcodeDetector =
        new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();

final CameraSource cameraSource = new CameraSource
        .Builder(this, barcodeDetector)
        .setRequestedPreviewSize(metrics.widthPixels, metrics.heightPixels / 4)
        .setAutoFocusEnabled(true)
        .build();

cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                    cameraSource.start(cameraView.getHolder());
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });

如何裁剪相机预览?只需要底部的 1/4 部分。

还需要添加一个带有矩形取景器的透明层。

您可能希望使用的是 TextureViewSurfaceViews 并非设计用于裁剪 - 视频显示调整为 SurfaceView 的大小是预期的行为。

另一方面,从 API 级别 14+ 开始可用的 TextureViews 允许您设置 .setTransform(Matrix matrix),其中矩阵包含有关如何缩放的数据视频,.setTranslationX(float x).setTranslationY(float y) 裁剪视频。有一个很好的例子 here.

如果您绝对必须使用 SurfaceView,我建议您考虑使用 GLSurfaceView 和可缩放视频的自定义渲染器。一个好的起点是 .

您无法通过缩小视图来实现裁剪。可以用另一种布局叠加相机预览,有效隐藏图片上3/4

我用ViewGroup解决了。

布局中:

    <com.superup.smartshelf.barcode.BarcodeCameraPreview
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.25"/>

在class中:

public class BarcodeCameraPreview extends ViewGroup {

private SurfaceView mSurfaceView;

public BarcodeCameraPreview(final Context context, AttributeSet attrs) {
    super(context, attrs);

    mSurfaceView = new SurfaceView(context);
    mSurfaceView.getHolder().addCallback(new SurfaceCallback());
    addView(mSurfaceView);
}

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // crop view
        int actualPreviewWidth = getResources().getDisplayMetrics().widthPixels;
        int actualPreviewHeight = getResources().getDisplayMetrics().heightPixels;


        if (mSurfaceView != null) {
            mSurfaceView.layout(0, 0, actualPreviewWidth, actualPreviewHeight);
        }
    }

// camera methods

}

在activity中:

BarcodeCameraPreview camera = (BarcodeCameraPreview) findViewById(R.id.preview);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels / 4);
camera.setLayoutParams(layoutParams);