Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android textureview full screen preview with correct aspect ratio

I have been working with the camera2 api demo from google and unfortunately the sample application is built to display the textureview preview at approximately 70% of the screen height, after looking around I was able to determine that this was being caused by the AutoFitTextureView overriding the onMeasure() method as shown below:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    if (0 == mRatioWidth || 0 == mRatioHeight) {
        setMeasuredDimension(width, height);
    } else {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        } else {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        }
    }
}

I attempted to correct this by setting the correct heights and widths in setMeasuredDimension(width, height);, this fixed the height issue and gave me a full screen preview from the textureview, however the aspect ratio is completely broken and warped on every device, what is the standard way of fixing this? I see many apps on the play store have found a way to solve this problem but havent been able to track down a fix, any help will go a long way, thanks.

like image 780
Edmund Rojas Avatar asked Jul 22 '16 21:07

Edmund Rojas


2 Answers

I was able to fix the issue by switching setMeasuredDimension();

    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    if (0 == mRatioWidth || 0 == mRatioHeight) {
        setMeasuredDimension(width, height);
    } else {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        } else {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        }
    }
like image 65
Edmund Rojas Avatar answered Sep 22 '22 13:09

Edmund Rojas


Below is the code that we used to measure a preview which supports 4:3, 16:9 and 1:1 preview sizes. The height is scaled because the app is block in portrait, it does not rotate to landscape.

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    Log.d(TAG, "[onMeasure] Before transforming: " + width + "x" + height);

    int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
    boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;

    int newWidth;
    int newHeight;

    Log.d(TAG, "[onMeasure] Get measured dimensions: " + getMeasuredWidth() + "x" + getMeasuredHeight());

    if (isInHorizontal) {
        newHeight = getMeasuredHeight();
        if (mAspectRatioOneOne) newWidth = getMeasuredHeight();
        else newWidth = (int) (newHeight * mAspectRatio);
    } else {
        newWidth = getMeasuredWidth();
        if (mAspectRatioOneOne) newHeight = getMeasuredWidth();
        else newHeight = (int) (newWidth * mAspectRatio);
    }

    setMeasuredDimension(newWidth, newHeight);
    Log.d(TAG, "[onMeasure] After transforming: " + getMeasuredWidth() + "x" + getMeasuredHeight());

}
like image 24
Francisco Durdin Garcia Avatar answered Sep 18 '22 13:09

Francisco Durdin Garcia