3

I am trying to implement my Preview View inside a BottomSheet. Everything is working fine except that the preview size changes as show in below image. See the image here

As you can see the preview is getting out of the bottom sheet while I have set the Preview View height to 175dp. It changes to 469 dp at runtime. Below is my XML of bottomsheet.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <androidx.camera.view.PreviewView
        android:id="@+id/camera"
        android:layout_width="match_parent"
        android:layout_height="175dp"
        android:layout_marginStart="12dp"
        android:layout_marginTop="12dp"
        android:layout_marginEnd="12dp"
        android:contentDescription="nothing"

        app:scaleType="fitCenter">

    </androidx.camera.view.PreviewView>

    <Button
        android:id="@+id/capture"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:background="@android:drawable/ic_menu_camera" />
</LinearLayout>

Below is my java startCamera and bindPreview functions.

private void startCamera() {

        final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(AddNotesActivity.this);

        cameraProviderFuture.addListener(new Runnable() {
            @Override
            public void run() {
                try {

                    ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                    bindPreview(cameraProvider);

                } catch (ExecutionException | InterruptedException e) {
                    // No errors need to be handled for this Future.
                    // This should never be reached.
                }
            }
        }, ContextCompat.getMainExecutor(AddNotesActivity.this));
    }

 void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {

        Preview preview = new Preview.Builder()
                .build();

        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build();

        ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .build();

        ImageCapture.Builder builder = new ImageCapture.Builder();

        //Vendor-Extensions (The CameraX extensions dependency in build.gradle)
        HdrImageCaptureExtender hdrImageCaptureExtender = HdrImageCaptureExtender.create(builder);

        // Query if extension is available (optional).
        if (hdrImageCaptureExtender.isExtensionAvailable(cameraSelector)) {
            // Enable the extension if available.
            hdrImageCaptureExtender.enableExtension(cameraSelector);
        }

        final ImageCapture imageCapture = builder
                .setTargetRotation(Surface.ROTATION_0)
                .build();

        mPreviewView.setScaleType(PreviewView.ScaleType.FILL_CENTER);
      
        preview.setSurfaceProvider(mPreviewView.getSurfaceProvider());

        Toast.makeText(this, ""+mPreviewView.getHeight()+"---"+mPreviewView.getWidth(), Toast.LENGTH_SHORT).show();
        Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis, imageCapture);

        capture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bitmap image = mPreviewView.getBitmap();
                Toast.makeText(AddNotesActivity.this, "Captured", Toast.LENGTH_SHORT).show();

            }
        });

    }

I need that preview view to stay inside the bottomsheet.

  • 6
    This is probably happening because PreviewView's using a SurfaceView underneath the hood. Could you set it to use a TextureView instead (call [PreviewView.setImplementationMode()](https://developer.android.com/reference/androidx/camera/view/PreviewView#setImplementationMode(androidx.camera.view.PreviewView.ImplementationMode)) and pass it [ImplementationMode.COMPATIBLE](https://developer.android.com/reference/androidx/camera/view/PreviewView.ImplementationMode#COMPATIBLE)). – Husayn Hakeem Apr 05 '21 at 16:22
  • Thanks dude It really got my work done – Santosh Kumar Apr 11 '21 at 12:05
  • @HusaynHakeem thanks it works. But SurfaceView is recommended in API >= 24. How come going against the Google recommendations is a way to resolve a seemingly unrelated issue with the preview height? :( – Varvara Kalinina May 13 '21 at 14:35
  • @VarvaraKalinina Fair point, even though the issue isn't really about the preview height, it's more about the surface the preview is rendered on. The need to use a TextureView in this scenario (PreviewView in a ViewPager) is more of a constraint of PreviewView, which stems from it handling both the view and camera stacks. Using a TextureView allows for certain behaviors which SurfaceView does not support (at least not with the way things are currently built in PreviewView). Using SurfaceView is a nicety, as it offers performance benefits, but there are certain cases it's not suited for. – Husayn Hakeem May 13 '21 at 16:14
  • @HusaynHakeem Could you copy your comment here to full answer below? I found this question and first time I didn't see your comment and close this page. Only second time I read your answer in comments – Danil Valov Apr 27 '23 at 09:36

0 Answers0