android - open - Ajustar una vista previa de la cámara a un SurfaceView más grande que la pantalla
open camera android developer (1)
Tengo una aplicación de Android que necesita para pantalla completa una vista previa de cámara, independientemente del tamaño de vista previa proporcionado por getSupportedPreviewSizes()
sin distorsión. Espero que esto recorte la vista previa en cierta cantidad, ya sea en la altura o el ancho, pero esto no me concierne. La razón por la que intento hacerlo es porque ciertas cámaras Android (por ejemplo, la cámara frontal Samsung Galaxy SII) no devuelven ninguna vista previa con la misma relación de aspecto que la pantalla, y por lo tanto deben estirarse y recortarse.
¿Es posible hacer crecer completamente la vista previa de la cámara a una vista más grande que el tamaño de visualización? Es posible hacer que SurfaceView sea más grande que las dimensiones de píxeles de vista previa devueltas simplemente configurando los parámetros de diseño de la vista de superficie para match_parent, pero esto produce distorsión en alguna dirección y solo es posible hasta que la vista previa llene la pantalla. Esto parece indicar que la vista previa fuera de la pantalla es imposible, y el hardware (u OS) limita dicho comportamiento.
Hay otra pregunta sobre el tema, pero esa pregunta afirma que no es posible crear un SurfaceView mayor que las dimensiones de la pantalla, que es falso, como he encontrado con el registro. Sin embargo, lo que parece ser el caso es que la vista previa de la cámara no puede crecer al tamaño completo de una enorme SurfaceView.
Mi intento:
Tengo un diseño relativo, dentro de él un FrameLayout, y dentro de eso creo un SurfaceView. El ancho de toda la disposición relativa se establece a continuación en 635 pb, que es ~ el doble del tamaño de la pantalla del dispositivo. FrameLayout coincide con este tamaño y también lo hace SurfaceView (agregado programáticamente más adelante)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/camera_activity_layout"
android:layout_width="635dp"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</RelativeLayout>
El siguiente es el código que obtiene y establece el tamaño de vista previa. Aquí quiero hacer que la vista previa de la cámara se expanda para llenar todo el FrameLayout (el doble del ancho de la pantalla). La vista se muestra y se destruye totalmente normalmente, así que elimino el código que no está relacionado con esta pregunta en particular porque distrae de la pregunta esencial y mi intento de aumentar la vista de manera simple y sencilla a un tamaño mayor que el de la pantalla.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
...
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
final DisplayMetrics dm = this.getResources().getDisplayMetrics();
//getBestPreviewSize returns the best preview size, don''t worry
//but some devices do not return one for all camera matching the aspect ratio
cameraSize = getBestPreviewSize(parameters, dm.heightPixels, dm.widthPixels);
if (cameraSize!=null) {
parameters.setPreviewSize(cameraSize.width, cameraSize.height);
mCamera.setParameters(parameters);
}
FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams) this.getLayoutParams();
frameParams.width = 800; //For argument''s sake making this ~double the width of the display. Same result occurs if I use MATCH_PARENT
frameParams.height = LayoutParams.MATCH_PARENT;
this.setLayoutParams(frameParams);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
Log.d("surfChange","W/H of CamPreview (child) is "+this.getWidth()+"/"+this.getHeight()+" while parent is ");
Log.d("surfChange","W/H of holder (child) is "+mHolder.getSurfaceFrame().width()+"/"+mHolder.getSurfaceFrame().height()+" while parent is ");
} catch (Exception e){
}
}
};
Me preocupa que la única forma de tener éxito en este empeño sea renderizar de alguna manera en una superficie OpenGL, pero apparently esto podría ser demasiado lento a todo color. También es un dolor si la vista previa de la cámara simplemente se puede estirar y recortar.
Gracias de antemano por cualquier intento de solución.
Ok, sé que esto es muy tarde como respuesta, pero es posible. A continuación se muestra el código de la muestra del SDK de Android. Para ver el resto del código para implementar esto, descarga los ejemplos de SDK de Android y ve a Samples/android-10(one I used, could try whichever you want to target)/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.java
class PreviewSurface extends ViewGroup implements SurfaceHolder.Callback {
...
@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.width;
previewHeight = mPreviewSize.height;
}
// 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);
}
}
}
}
este código está destinado a ajustarse a la vista previa de la dimensión más pequeña (que no estropea la proporción de aspcect) y al centro para tener barras negras en la otra dimensión. Pero si voltea el >
ser <
en su lugar, conseguirá lo que quiere. Ex:
if (width * previewHeight < height * previewWidth) {...