Jak narysować nakładkę na widoku SurfaceView używanym przez kamerę na Androida?

Mam prosty program, który rysuje podgląd Camera do SurfaceView. Próbuję użyć metody onPreviewFrame, która jest wywoływana za każdym razem, gdy nowa ramka jest rysowana do SurfaceView, w celu wykonania metody invalidate, która ma wywoływać metodę onDraw. W rzeczywistości wywoływana jest metoda onDraw, ale nic tam nie jest drukowane (domyślam się, że podgląd kamery nadpisuje tekst, który próbuję narysować).

Jest to uproszczona wersja SurfaceView podklasy I mieć:

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);
 }
}
Author: Cristian, 2010-05-29

3 answers

SurfaceView prawdopodobnie nie działa jak zwykły View w tym zakresie.

Zamiast tego wykonaj następujące czynności:

  1. Put your SurfaceView inside of a FrameLayout lub RelativeLayout w Twój plik XML układu, ponieważ zarówno pozwalają one układać widżety na oś Z
  2. Przenieś swoją logikę rysowania do osobnej klasy View
  3. Dodaj instancję widoku niestandardowego klasy do pliku XML układu jako dziecko FrameLayout lub RelativeLayout, ale czy wydaje się po SurfaceView

Spowoduje to, że Twoja niestandardowa klasa View pojawi się unosząc się nad SurfaceView.

Zobacz przykładowy projekt , który warstwuje panele wyskakujące nad SurfaceView używane do odtwarzania wideo.

 83
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-02 05:15:27

Spróbuj wywołać setWillNotDraw(false) z 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");
}

I wywołanie invalidate z onTouchEvent:

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
 17
Author: maximus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 23:19:18

Myślę, że powinieneś najpierw wywołać metodę super.draw(), zanim zrobisz cokolwiek w metodzie rysowania surfaceView.

 1
Author: Devashish Kunal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 09:12:01