web-dev-qa-db-fra.com

Comment dessiner une superposition sur une SurfaceView utilisée par Camera sur Android?

J'ai un programme simple qui dessine l'aperçu du Camera dans un SurfaceView. Ce que j'essaie de faire, c’est d’utiliser la méthode onPreviewFrame, qui est appelée chaque fois qu’un nouveau cadre est dessiné dans le SurfaceView, afin d’exécuter la méthode invalidate qui est supposé invoquer la méthode onDraw. En fait, la méthode onDraw est invoquée, mais rien n’est en cours d’impression (je suppose que l’aperçu de la caméra remplace le texte que je tente de dessiner).

Ceci est une version simplifiée de la sous-classe SurfaceView que j'ai:

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);
 }
}
68
Cristian

SurfaceView ne fonctionne probablement pas comme un View ordinaire à cet égard.

Au lieu de cela, procédez comme suit:

  1. Placez votre SurfaceView à l'intérieur d'un FrameLayout ou RelativeLayout dans votre fichier XML de présentation, car ces deux éléments permettent d'empiler des widgets sur l'axe des z
  2. Déplacez votre logique de dessin dans une classe View distincte et personnalisée
  3. Ajoutez une instance de la classe View personnalisée au fichier XML de présentation en tant qu'enfant de FrameLayout ou RelativeLayout, mais faites-la apparaître après le SurfaceView.

Cela fera apparaître votre classe personnalisée View comme flottant au-dessus de SurfaceView.

Voir ici pour un exemple de projet qui superpose les panneaux popup au-dessus d'un SurfaceView utilisé pour la lecture vidéo.

84
CommonsWare

Essayez d'appeler setWillNotDraw(false) depuis 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");
}

et en appelant invalidate à partir de onTouchEvent:

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
17
maximus

Je pense que vous devriez d'abord appeler la méthode super.draw() avant de faire quoi que ce soit dans la méthode draw de surfaceView.

1
Devashish Kunal