¿Cómo dibujar una superposición en un SurfaceView utilizado por la cámara en Android?

Tengo un progtwig simple que dibuja la vista previa de la Camera en un SurfaceView . Lo que trato de hacer es usar el método onPreviewFrame , que se invoca cada vez que se dibuja un nuevo marco en SurfaceView , para ejecutar el método de invalidate que se supone que invoca el método onDraw . De hecho, se onDraw método onDraw , pero no se está imprimiendo nada (supongo que la vista previa de la cámara sobrescribe el texto que bash dibujar).

Esta es una versión simplificada de la subclase SurfaceView que tengo:

 public class Superficie extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder mHolder; public Camera camera; Superficie(Context context) { super(context); mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(final SurfaceHolder holder) { camera = Camera.open(); try { camera.setPreviewDisplay(holder); camera.setPreviewCallback(new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera arg1) { invalidar(); } }); } catch (IOException e) {} } public void invalidar(){ invalidate(); } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(w, h); camera.setParameters(parameters); camera.startPreview(); } @Override public void draw(Canvas canvas) { super.draw(canvas); // nothing gets drawn :( Paint p = new Paint(Color.RED); canvas.drawText("PREVIEW", canvas.getWidth() / 2, canvas.getHeight() / 2, p); } } 

SurfaceView probablemente no funciona como una View normal en este sentido.

En cambio, haz lo siguiente:

  1. Ponga su SurfaceView dentro de un FrameLayout o RelativeLayout en su archivo XML de diseño, ya que ambos permiten el astackmiento de widgets en el eje Z.
  2. Mueva su lógica de dibujo a una clase de View personalizada separada
  3. Agregue una instancia de la clase Vista personalizada al archivo XML de diseño como elemento secundario de FrameLayout o RelativeLayout , pero SurfaceView que aparezca después de SurfaceView

Esto hará que su clase de View personalizada parezca flotar sobre SurfaceView .

Vea aquí un ejemplo de proyecto que SurfaceView paneles emergentes sobre un SurfaceView utilizado para la reproducción de videos.

Intente llamar a setWillNotDraw(false) desde surfaceCreated :

 public void surfaceCreated(SurfaceHolder holder) { try { setWillNotDraw(false); mycam.setPreviewDisplay(holder); mycam.startPreview(); } catch (Exception e) { e.printStackTrace(); Log.d(TAG,"Surface not created"); } } @Override protected void onDraw(Canvas canvas) { canvas.drawRect(area, rectanglePaint); Log.w(this.getClass().getName(), "On Draw Called"); } 

y llamar a invalidate desde onTouchEvent :

 public boolean onTouch(View v, MotionEvent event) { invalidate(); return true; } 

Creo que debes llamar primero al método super.draw() antes de hacer algo en el método de sorteo de SurfaceView.