我知道有很多问题要问这个问题。我尝试了其中一些。但没有什么对我有用。以下是我创建预览的方法
TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
fetchCameraData();
prepareSurface();
prepareCameraDevice(cameraId);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture)
{
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
private void prepareCamera() {
previewView = (AutoFitTextureView) findViewById(R.id.textureview);
previewView.setSurfaceTextureListener(listener);
}
private void fetchCameraData() {
cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraID : cameraManager.getCameraIdList()) {
cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID);
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
cameraId = cameraID;
StreamConfigurationMap streamConfigs = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
previewSize = Collections.max(
Arrays.asList(streamConfigs.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
break;
}
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(this, "Unable to fetch camera data", Toast.LENGTH_SHORT).show();
}
}
private void prepareSurface() {
SurfaceTexture texture = previewView.getSurfaceTexture();
textureSurface = new Surface(texture);
jpegReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(), ImageFormat.JPEG, 1);
jpegSurface = jpegReader.getSurface();
jpegReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
Image image = imageReader.acquireLatestImage();
ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
byte jpegBytes[] = new byte[byteBuffer.remaining()];
byteBuffer.get(jpegBytes);
Bitmap imageBitmap = BitmapFactory.decodeByteArray(jpegBytes, 0, jpegBytes.length);
capturedImage = imageBitmap;
decodeBase64Image(getBase64Image(imageBitmap));
image.close();
}
}, null);
}
private void prepareCameraDevice(String cameraId) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
try {
cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
prepareCaptureSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
}
@Override
public void onError(@NonNull CameraDevice cameraDevice, int i) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(this, "Unable to user Camera", Toast.LENGTH_SHORT).show();
}
} else {
requestPermission();
}
}
private void prepareCaptureSession() {
List<Surface> surfaceList = Arrays.asList(textureSurface, jpegSurface);
try {
mCameraDevice.createCaptureSession(surfaceList, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
session = cameraCaptureSession;
startCamera();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
Toast.makeText(this, "Unable to create session", Toast.LENGTH_SHORT).show();
}
}
private void startCamera() {
try {
requestPreview = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestPreview.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
requestPreview.addTarget(textureSurface);
session.setRepeatingRequest(requestPreview.build(), null, null);
} catch (CameraAccessException e) {
Toast.makeText(this, "Unable to create preview", Toast.LENGTH_SHORT).show();
}
}
我的AutoFitTextureView类如下
public class AutoFitTextureView extends TextureView {
private int mRatioWidth = 0;
private int mRatioHeight = 0;
public AutoFitTextureView(Context context) {
this(context, null);
}
public AutoFitTextureView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
/**
* Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
* calculated from the parameters. Note that the actual sizes of parameters don't matter, that
* is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
*
* @param width Relative horizontal size
* @param height Relative vertical size
*/
public void setAspectRatio(int width, int height) {
if (width < 0 || height < 0) {
throw new IllegalArgumentException("Size cannot be negative.");
}
if (mRatioWidth == width && mRatioHeight == height) {
return;
}
mRatioWidth = width;
mRatioHeight = height;
requestLayout();
}
@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);
}
}
}
}
这是我的xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="in.thoughtsmith.miinterface.MainActivity">
<Button
android:id="@+id/scanButton"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="10dp"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:alpha="0.50"
android:background="@drawable/button_shape"
android:text="Scan"
android:textColor="@color/white" />
<in.thoughtsmith.miinterface.AutoFitTextureView
android:id="@+id/textureview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:id="@+id/captureImage"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="@+id/buyButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginBottom="10dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:alpha="0.5"
android:background="@drawable/button_shape"
android:text="Buy"
android:textColor="@color/white" />
<Button
android:id="@+id/accessoriesButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginBottom="10dp"
android:layout_marginEnd="5dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:alpha="0.5"
android:background="@drawable/button_shape"
android:text="Accessories"
android:textColor="@color/white" />
</LinearLayout>
</RelativeLayout>
上面的代码在某些设备中给出了扭曲的预览图像。它给我在OnePlus 3T设备上的扭曲预览显示。
答案 0 :(得分:1)
将layout_width和layout_height更改为&#34; wrap_content&#34;,而不是&#34; match_parent&#34;为您的AutoFitTextureView。
&#34; match_parent&#34;不要让View覆盖你需要的大小。