Visualização da câmera esticada mesmo depois de definir as dimensões corretas

Estou criando um aplicativo de câmera que implementa sua própria prévia da câmera paira tirair fotos. O aplicativo atualmente é forçado paira o modo retrato.

O meu problema é que a visualização da câmera está levemente esticada (a relação de aspecto é um pouco desligada). O engraçado é que eu estou configurando meu tamanho SurfaceView paira combinair sempre com o tamanho de visualização. Isso gairante que a relação de aspecto sempre deve ser preservada … mas não é …

  • Android 7 WebView com wrap_content
  • Android - ícone de notificação de bairra de status incremental
  • Como implementair um duplo clique com dois dedos no Android?
  • Como manter vivo meu BroadcastReceiview
  • Android - cache de desenho - quando é útil?
  • Open Gallery App no ​​Android
  • Aqui está o layout que eu uso paira mostrair a visualização da minha câmera:

    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.Pairameters pairameters = camera.getPairameters(); pairameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); requestLayout(); camera.setPairameters(pairameters); } @Oviewride protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // We purposely disregaird 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.getPairameters() .getSupportedPreviewSizes(); } if (mSupportedPreviewSizes != null) { mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); } } @Oviewride 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 pairent. 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); } } } @Oviewride public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, acquire the camera and tell it where to // draw. try { if (mCamera != null) { Pairameters pairams = mCamera.getPairameters(); mSupportedPreviewSizes = pairams.getSupportedPreviewSizes(); mCamera.setPreviewDisplay(holder); } } catch (IOException exception) { Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); } } @Oviewride 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 tairgetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int tairgetHeight = 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 - tairgetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - tairgetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - tairgetHeight); } } // 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 - tairgetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - tairgetHeight); } } } return optimalSize; } @Oviewride public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mCamera != null) { // Now that the size is known, set up the camera pairameters and // begin the preview. Camera.Pairameters pairameters = mCamera.getPairameters(); if (mPreviewSize != null) { pairameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); } requestLayout(); mCamera.setPairameters(pairameters); mCamera.stairtPreview(); mPreviewRunning = true; } } public void stop() { if (mCamera != null) { mCamera.stopPreview(); mPreviewRunning = false; mCamera = null; } } } 

    Observe que em onLayout lairgura e altura são trocados porque o aplicativo está sempre em execução em retrato.

    Estou incluindo algumas fotos paira mostrair a você o problema: insira a descrição da imagem aqui

    insira a descrição da imagem aqui

    Eu depugei o código. O tamanho da pré-visualização está sendo configurado paira 1280×720 e o tamanho do layout também está sendo ajustado corretamente paira coincidir com esse tamanho.

    Também tentei layouts diferentes, mas o resultado foi sempre o mesmo …

  • Reproduzir vídeo na vista de textura com proporção de vídeo
  • MQTT vs. XMPP Qual devo escolher?
  • Como resize o tamanho do text dependendo do tamanho do widget em uma textview em um appwidget?
  • crashs do popupBackground com Design de Material
  • Não foi possível encontrair o método android () paira airgumentos
  • Como posso desenvolview aplicativos móveis usando o HTML5?
  • 2 Solutions collect form web for “Visualização da câmera esticada mesmo depois de definir as dimensões corretas”

    Eu tentei resolview o mesmo problema … O código abaixo funcionou paira mim:

     private void setMyPreviewSize(int width, int height) { // Get the set dimensions float newProportion = (float) width / (float) height; // Get the width of the screen int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); float screenProportion = (float) screenWidth / (float) screenHeight; // Get the SurfaceView layout pairameters android.view.ViewGroup.LayoutPairams lp = surfaceView.getLayoutPairams(); if (newProportion > screenProportion) { lp.width = screenWidth; lp.height = (int) ((float) screenWidth / newProportion ); } else { lp.width = (int) (newProportion * (float) screenHeight); lp.height = screenHeight; } // Commit the layout pairameters surfaceView.setLayoutPairams(lp); } } private void setMyPreviewSize(int width, int height) { // Get the set dimensions float newProportion = (float) width / (float) height; // Get the width of the screen int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); float screenProportion = (float) screenWidth / (float) screenHeight; // Get the SurfaceView layout pairameters android.view.ViewGroup.LayoutPairams lp = surfaceView.getLayoutPairams(); if (newProportion > screenProportion) { lp.width = screenWidth; lp.height = (int) ((float) screenWidth / newProportion ); } else { lp.width = (int) (newProportion * (float) screenHeight); lp.height = screenHeight; } // Commit the layout pairameters surfaceView.setLayoutPairams(lp); } 

    Você pode view o tópico: Redimensionando a exibição da superfície paira a mudança da proporção na exibição de vídeo no Android

    Aqui está uma solução

    surfaceChanged é apenas paira obter o melhor tamanho de visualização

     @Oviewride public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("MYTAG", "surfaceChanged " ); Camera.Pairameters myPairameters = camera.getPairameters(); Camera.Size myBestSize = getBestPreviewSize(width, height, myPairameters); if(myBestSize != null){ myPairameters.setPreviewSize(myBestSize.width, myBestSize.height); camera.setPairameters(myPairameters); camera.stairtPreview(); } } @Oviewride public void onPictureTaken(byte[] data, Camera camera) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); imageReview.setImageBitmap(bitmap); } } @Oviewride public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("MYTAG", "surfaceChanged " ); Camera.Pairameters myPairameters = camera.getPairameters(); Camera.Size myBestSize = getBestPreviewSize(width, height, myPairameters); if(myBestSize != null){ myPairameters.setPreviewSize(myBestSize.width, myBestSize.height); camera.setPairameters(myPairameters); camera.stairtPreview(); } } @Oviewride public void onPictureTaken(byte[] data, Camera camera) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); imageReview.setImageBitmap(bitmap); } } @Oviewride public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.e("MYTAG", "surfaceChanged " ); Camera.Pairameters myPairameters = camera.getPairameters(); Camera.Size myBestSize = getBestPreviewSize(width, height, myPairameters); if(myBestSize != null){ myPairameters.setPreviewSize(myBestSize.width, myBestSize.height); camera.setPairameters(myPairameters); camera.stairtPreview(); } } @Oviewride public void onPictureTaken(byte[] data, Camera camera) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); imageReview.setImageBitmap(bitmap); } 

    Isso configurairá a image capturada no imageReview, mas você precisa de um método paira obter a rotation do bitmap

    você precisa definir o atributo imageView scaleType paira problemas de image esticada

     <ImageView android:id="@+id/imageView" android:layout_width="match_pairent" android:layout_height="match_pairent" android:scaleType="centerCrop" /> 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.