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.
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);
}
}
I let you below 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.
Hope it will help you or someone else with the same problem!
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());
}
If you want full-screen, undistorted preview, then you have to select a preview resolution for the camera that matches the aspect ratio of your screen.
However, if your screen size isn't a standard size (16:9 or 4:3, basically), especially once you subtract off the soft buttons and the notification bar (assuming you're not completely full screen), then the only option for having the preview fill the screen is to cut some of it off.
You should be able to modify the TextureView's transform matrix to remove the distortion, by looking at the view's width and height and the selected preview width and height, but this will necessarily cut some of it off.