Tôi đang tạo một ứng dụng máy ảnh triển khai chế độ xem trước máy ảnh của chính nó để chụp ảnh. Ứng dụng hiện được buộc vào chế độ dọc.Xem trước máy ảnh được kéo dài ngay cả sau khi đã đặt đúng kích thước
Vấn đề của tôi là bản xem trước từ máy ảnh hơi bị kéo dài (tỷ lệ cỡ ảnh hơi lệch). Điều thú vị là tôi đang thiết lập kích thước SurfaceView của mình để luôn khớp với kích thước xem trước. Điều này đảm bảo rằng tỷ lệ khía cạnh nên luôn luôn được perserved ... nhưng nó không phải là ...
Dưới đây là cách bố trí tôi sử dụng để hiển thị xem trước máy ảnh của tôi:
public class Cp extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
private boolean mPreviewRunning = false;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private Camera mCamera;
public boolean IsPreviewRunning() {
return mPreviewRunning;
}
public Cp(Context context) {
this(context, null, 0);
}
public Cp(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Cp(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
requestLayout();
}
}
public void switchCamera(Camera camera) {
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
camera.setParameters(parameters);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a wrapper to
// a SurfaceView that
// centers the camera preview instead of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes == null && mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters()
.getSupportedPreviewSizes();
}
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
height);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed && getChildCount() > 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.height;
previewHeight = mPreviewSize.width;
}
if (previewWidth == 0) {
previewWidth = 1;
}
if (previewHeight == 0) {
previewHeight = 1;
}
// Center the child SurfaceView within the parent.
if (width * previewHeight > 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);
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where to
// draw.
try {
if (mCamera != null) {
Parameters params = mCamera.getParameters();
mSupportedPreviewSizes = params.getSupportedPreviewSizes();
mCamera.setPreviewDisplay(holder);
}
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
stop();
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w/h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width/size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mCamera != null) {
// Now that the size is known, set up the camera parameters and
// begin the preview.
Camera.Parameters parameters = mCamera.getParameters();
if (mPreviewSize != null) {
parameters.setPreviewSize(mPreviewSize.width,
mPreviewSize.height);
}
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
mPreviewRunning = true;
}
}
public void stop() {
if (mCamera != null) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera = null;
}
}
}
Xin lưu ý rằng trong onLayout
chiều rộng và chiều cao được đổi chỗ vì ứng dụng luôn chạy theo chiều dọc.
tôi bao gồm một số hình ảnh để hiển thị cho bạn những gì các vấn đề trông giống như:
Tôi đã sửa lỗi mã. Kích thước xem trước được đặt thành 1280x720 và kích thước bố cục cũng được điều chỉnh chính xác để phù hợp với kích thước đó.
Tôi cũng đã cố gắng bố trí khác nhau nhưng kết quả là luôn luôn giống nhau ...
đã không kiểm tra nó hoàn toàn được nêu ra, nhưng điều này thực sự có vẻ làm việc. Tốt đẹp. –
Giải pháp này không hoạt động đối với tôi. Vui lòng tham khảo câu hỏi của tôi http: // stackoverflow.com/questions/21107208/how-to-make-camera-preview-size-same-as-imageview-size-without-preview-stretch –
getBestPreviewSize() luôn mang lại cho tôi kích thước nhỏ hơn của máy ảnh và cùng một vấn đề xảy ra khi xem căng. –