tutorial studio intent example create app android camera

studio - Vista previa de la cámara estirada en pocos dispositivos Android



intent camera android (3)

Estoy creando una cámara personalizada como "SnapChat" para una aplicación de Android, pero la vista previa de la cámara se extiende en Pocos dispositivos como (Moto g de segunda generación, uno + uno) pero no en (Samsung s3, Samsung s4). He utilizado la siguiente referencia La visualización / vista previa de la cámara en pantalla completa no mantiene la relación de aspecto: la imagen está sesgada, estirada para que quepa en la pantalla . Pero esto no me ayuda al 100%. Estoy compartiendo la pantalla.

Imagen estirada en Samsung Moto G de segunda generación es.

Las imágenes del Samsung S3 que no se estiran están arriba.

private void setPreviewLayout() { if (null == mCamera) { return; } Camera.Parameters parameters = null; Camera.Size size = null; try { int screenWidth = (int) getResources().getDisplayMetrics().widthPixels; int screenHeight = (int) getResources().getDisplayMetrics().heightPixels; parameters = mCamera.getParameters(); size = getOptimalPreviewSize(mCamera.getParameters().getSupportedPreviewSizes(), screenWidth, screenHeight); if (size != null) { parameters.setPreviewSize(size.width, size.height); } parameters.setPictureSize(screenHeight, screenWidth); ; mCamera.setParameters(parameters); if (on && currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON); } else { parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); } parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO); parameters.setExposureCompensation(0); parameters.setPictureFormat(ImageFormat.JPEG); parameters.setJpegQuality(100); List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } mCamera.setParameters(parameters); /* * camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); */ } catch (Exception e) { e.printStackTrace(); } } private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) h / w; if (sizes == null) return null; Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; for (Camera.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); } } if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; }


Debe anular el método onMeasure de la clase SurfaceView para obtener el ancho y el alto de la vista de superficie

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); if (mSupportedPreviewSizes != null) { mPreviewSize = getOptimalPreviewSize(mCamera.getParameters().getSupportedPreviewSizes(), width, height); } }

A continuación, configure el tamaño de vista previa que tiene en el tamaño de vista previa de los parámetros de la cámara.

cameraParameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); mCamera.setParameters(cameraParameters);

getSuggestedMinimumHeight (), getSuggestedMinimumWidth () son los métodos de la clase View.

Espero que esto ayude !!!


Usar getOptimalPreviewSize() es importante, pero no resuelve todo el estiramiento en todos los dispositivos en todos los diseños. Debe estar preparado para recortar la vista previa un poco, de modo que la vista previa llene la pantalla sin distorsión.

Existen diferentes técnicas para forzar el tamaño de la superficie diferente del tamaño real de la pantalla, pero a esta la encuentro más fácil:

Añado el CameraView a mi diseño:

public class CameraView extends SurfaceView implements SurfaceHolder.Callback { public CameraView(Context context, AttributeSet attr) { super(context, attr); // install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. getHolder().addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { openCamera(); bCameraInitialized = false; } @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.release(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (bCameraInitialized) { // we will get here after we have resized the surface, see below return; } cameraSetup(w, h); bCameraInitialized = true; } private void cameraSetup(int w, int h) { // set the camera parameters, including the preview size FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); double cameraAspectRatio = ((double)optimalSize.width)/optimalSize.height; if (((double)h)/w > cameraAspectRatio) { lp.width = (int)(h/cameraAspectRatio+0.5); lp.height = h; } else { lp.height = (int)(w*cameraAspectRatio + 0.5); lp.width = w; lp.topMargin = (h - lp.height)/2; } lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; setLayoutParams(lp); requestLayout(); }

Para enfatizar la idea principal, no incluí el manejo de errores y no mostré aquí cómo la cámara se inicia realmente con un Looper secundario .


prueba esto esta funcionando ...

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "Camera Preview"; private static final double PREVIEW_SIZE_FACTOR = 3.00; private SurfaceHolder mHolder = null; private Camera mCamera = null; Camera.Parameters _parameters=null; @SuppressWarnings("deprecation") public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { Camera.Parameters parameters = mCamera.getParameters(); final Size mPreviewSize = getOptimalSize(); parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); requestLayout(); mCamera.setParameters(parameters); mCamera.setPreviewDisplay(holder); mCamera.startPreview(); //startContinuousAutoFocus(); } catch (Exception e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { } @SuppressLint("NewApi") public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // set Camera parameters // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } public void startPreview(){ try{ mCamera.startPreview(); }catch (Exception e) { } } private Size getOptimalSize() { Camera.Size result = null; final Camera.Parameters parameters = mCamera.getParameters(); Log.i(CameraPreview.class.getSimpleName(), "window width: " + getWidth() + ", height: " + getHeight()); for (final Camera.Size size : parameters.getSupportedPreviewSizes()) { if (size.width <= getWidth() * PREVIEW_SIZE_FACTOR && size.height <= getHeight() * PREVIEW_SIZE_FACTOR) { if (result == null) { result = size; } else { final int resultArea = result.width * result.height; final int newArea = size.width * size.height; if (newArea > resultArea) { result = size; } } } } if (result == null) { result = parameters.getSupportedPreviewSizes().get(0); } Log.i(CameraPreview.class.getSimpleName(), "Using PreviewSize: " + result.width + " x " + result.height); return result; } }