How to fix the right aspect ratio of the camera preview (surfaceview) in Android?
<p>I am creating the Android app with the camera functionality.
The camera screen contains the toolbar on the top, the surfaceview (camera preview) below the toolbar, and the camera control buttons on the bottom of the screen. The screen is always in portrait.</p>

<p>[Some lines of the code do not related to the issue are deleted]</p>

<p>This is my fragment <code>FragmentCamera</code></p>

<pre><code>import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.dmc.R;
import com.dmc.entities.Preview;

public class CameraFragment implements View.OnClickListener, View.OnTouchListener {

    public static final String ARG_CAMERA_MODE = "camera.mode";
    public static final String TYPE_CAMERA_MODE_IMAGE = "image";
    public static final String TYPE_CAMERA_MODE_VIDEO = "video";
    public MediaRecorder mrec = new MediaRecorder();

    private Camera camera;
    private String mCameraMode = TYPE_CAMERA_MODE_IMAGE; //or video
    private com.dmc.entities.Preview preview;
    private ImageView btnStopRecording;
    private SurfaceView surfaceView;
    private View view;

    public static FrCamera getInstance(String cameraMode) {
        CameraFragment fragment = new CameraFragment();
        Bundle bundle = new Bundle(1);
        bundle.putString(ARG_CAMERA_MODE, cameraMode);
        return fragment.setArguments(bundle);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCameraMode = getArguments().getString(ARG_CAMERA_MODE);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_camera, container, false);
        view.setOnTouchListener(this);
        btnStopRecording = (ImageView) view.findViewById(R.id.btnStopRecording);
        if (!mCameraMode.equals(TYPE_CAMERA_MODE_IMAGE)) {
            btnStopRecording.setOnClickListener(this);
        }
        surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
        view.findViewById(R.id.imgCameraTakePicture).setOnClickListener(this);

        preview = new Preview(getActivity(), (SurfaceView) view.findViewById(R.id.surfaceView));
        preview.setKeepScreenOn(true);
        return view;
    }

    @Override
    public void onStart() {
        super.onStart();

        int numCams = Camera.getNumberOfCameras();
        if (numCams &gt; 0) {
            try {
                camera = Camera.open(0);
                preview.setCamera(camera);
                camera.startPreview();
            } catch (RuntimeException ex) {
            }
        }
    }

    @Override
    public void onPause() {
        if (camera != null) {
            camera.stopPreview();
            preview.setCamera(null);
            camera.release();
            camera = null;
        }
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        camera.startPreview();
    }

    private void startVideoRecording() {
        try {
            mrec = new MediaRecorder();
            mrec.setCamera(camera);
            mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            mrec.setAudioSource(MediaRecorder.AudioSource.MIC);
            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
            mrec.setProfile(profile);
            camera.lock();
            camera.unlock();
            mrec.setPreviewDisplay(preview.mHolder.getSurface());
            mrec.setOutputFile(outVideoFile.getPath());
            mrec.setOrientationHint(Preview.rotate);
            mrec.prepare();
            mrec.start();
        } catch (Exception ex) {
            Log.e(getClass().getName(), ex.getMessage());
        }
    }

    protected void stopRecording() {
        if (mrec != null) {
            mrec.stop();
            mrec.release();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imgCameraTakenPicture:
                // Save image
                break;
            case R.id.btnStopRecording:
                stopRecording();
                break;
            case R.id.imgCameraTakePicture:
                if (mCameraMode.equals(TYPE_CAMERA_MODE_IMAGE)) {
                    camera.takePicture(shutterCallback, rawCallback, jpegCallback);
                } else
                    startVideoRecording();
                break;
        }
    }
}
</code></pre>

<p>This is the Preview</p>

<pre><code>import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;

import java.io.IOException;
import java.util.List;

public class Preview extends ViewGroup implements SurfaceHolder.Callback {
    public static final float RATIO = 0.75f;
    public static int rotate;

    public SurfaceView mSurfaceView;
    public SurfaceHolder mHolder;
    Size mPreviewSize;
    List&lt;Size&gt; mSupportedPreviewSizes;
    Camera mCamera;

    public Preview(Context context, SurfaceView sv) {
        super(context);
        mSurfaceView = sv;
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void setCamera(Camera camera) {
        mCamera = camera;
        if (mCamera != null) {
            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
            requestLayout();
            // get Camera parameters
            Camera.Parameters params = mCamera.getParameters();

            List&lt;String&gt; focusModes = params.getSupportedFocusModes();
            if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            } else {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            }

            params.setJpegThumbnailQuality(100);
            params.setJpegQuality(100);

            // Configure image format. RGB_565 is the most common format.
            List&lt;Integer&gt; formats = params.getSupportedPictureFormats();
            if (formats.contains(PixelFormat.RGB_565))
                params.setPictureFormat(PixelFormat.RGB_565);
            else if (formats.contains(PixelFormat.JPEG))
                params.setPictureFormat(PixelFormat.JPEG);
            else params.setPictureFormat(formats.get(0));

            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);
            int cameraRotationOffset = camInfo.orientation;

            Camera.Parameters parameters = mCamera.getParameters();

            int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
            int degrees = 0;
            switch (rotation) {
                case Surface.ROTATION_0:
                    degrees = 0;
                    break; // Natural orientation
                case Surface.ROTATION_90:
                    degrees = 90;
                    break; // Landscape left
                case Surface.ROTATION_180:
                    degrees = 180;
                    break;// Upside down
                case Surface.ROTATION_270:
                    degrees = 270;
                    break;// Landscape right
            }
            int displayRotation;
            if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                displayRotation = (cameraRotationOffset + degrees) % 360;
                //displayRotation = (360 - displayRotation) % 360; // compensate the mirror
            } else { // back-facing
                displayRotation = (cameraRotationOffset - degrees + 360) % 360;
            }
            mCamera.setDisplayOrientation(displayRotation);

            if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                rotate = (360 + cameraRotationOffset + degrees) % 360;
            } else {
                rotate = (360 + cameraRotationOffset - degrees) % 360;
            }

            parameters.set("orientation", "portrait");
            parameters.setRotation(rotate);

            mCamera.setParameters(params);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (changed &amp;&amp; getChildCount() &gt; 0) {
            final View child = getChildAt(0);

            final int width = r - l;
            final int height = b - t;

            int previewWidth = width;
            int previewHeight = height;
            if (mPreviewSize != null) {
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
            }

            // Center the child SurfaceView within the parent.
            if (width * previewHeight &gt; height * previewWidth) {
                final int scaledChildWidth = previewWidth * height / previewHeight;
                child.layout((width - scaledChildWidth) / 2, 0,
                        (width + scaledChildWidth) / 2, height);
            } else {
                final int scaledChildHeight = previewHeight * width / previewWidth;
                child.layout(0, (height - scaledChildHeight) / 2,
                        width, (height + scaledChildHeight) / 2);
            }
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            }
        } catch (IOException exception) {}
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mHolder.getSurface() == null) {
            return;
        }
        stopPreview();
        setCamera(mCamera);
        startPreview();
        mCamera.startPreview();
    }

    public void startPreview() {
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
            } 
        } catch (Exception e) {}
    }

    public void stopPreview() {
        try {
            if (mCamera != null)
                mCamera.stopPreview();
        } catch (Exception e) {}
    }
}
</code></pre>

<p>The expected result is on the image on left side. The obtained result is on the image on the right side. The camera preview is stretched. How to fix the right aspect ratio of the camera preview?
<a href="https://i.stack.imgur.com/l9xVh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/l9xVh.png" alt="enter image description here"></a></p>