Android - 如何使用 camera getSupportedPreviewSizes() 进行纵向定向
我正在尝试在活动中嵌入相机预览。而且它只在纵向方向上。问题是预览被拉伸了。
我试图选择最佳尺寸。但问题是所有支持的预览大小都来自横向返回大小。因此,根据我的代码选择正确的大小是行不通的。getSupportedPreviewSizes()
我的布局 XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_take_attendance"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:orientation="vertical"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.lab.rafael.smartattendance.TakeAttendanceActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/take_attendance_label"
android:id="@+id/take_attendance_label"
android:layout_marginBottom="@dimen/activity_vertical_margin"/>
<!-- camera preview container -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/red"
android:id="@+id/take_attendance_scan_qr_frame"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/take_attendance_manual_text"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/take_attendance_manual_button"
android:id="@+id/take_attendance_manual_button"/>
</LinearLayout>
</LinearLayout>
这是我的课程:CameraPreview
package com.lab.rafael.smartattendance.camera;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.List;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera mCamera = null;
private SurfaceHolder mHolder = null;
private Camera.Size optimalSize = null;
public CameraPreview(Context context, Camera camera)
{
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
if(focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
if(optimalSize != null) {
params.setPreviewSize(optimalSize.width, optimalSize.height);
}
mCamera.setParameters(params);
mCamera.startPreview();
} catch (IOException e)
{
Log.e("created_error", e.getMessage());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
Log.e("changed_error", e.getMessage());
}
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e){
Log.e("error", e.getMessage());
}
}
@Override
public void onMeasure(int measureWidthSpec, int measureHeightSpec) {
optimalSize = getOptimalSize(MeasureSpec.getSize(measureWidthSpec), MeasureSpec.getSize(measureHeightSpec));
setMeasuredDimension(optimalSize.width, optimalSize.height);
}
protected Camera.Size getOptimalSize(int width, int height) {
List<Camera.Size> supportedSizes = mCamera.getParameters().getSupportedPreviewSizes();
double targetRatio = (double) width / height,
optimalRatio = 0.0,
acceptableRatioMargin = 0.1,
minDiff = Double.MAX_VALUE;
for(Camera.Size size : supportedSizes) {
optimalRatio = (double) size.width / size.height;
if(Math.abs(optimalRatio - targetRatio) < acceptableRatioMargin) {
if(Math.abs(height - size.height) < minDiff) {
minDiff = Math.abs(height - size.height);
optimalSize = size;
}
}
}
if(optimalSize == null) {
for(Camera.Size size : supportedSizes) {
if(Math.abs(height - size.height) <= minDiff) {
minDiff = Math.abs(height - size.height);
optimalSize = size;
}
}
}
return optimalSize;
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
下图是由这些值生成的:
Specified resolution from measureSpecWidth/Height = `984x1335`
Returned from getOptimalSize() = `1600x1200`.
因为提供的是横向而不是纵向。supportedPreviewSizes
结果如下: