Как нарисовать наложение на SurfaceView, используемом камерой на Android? - PullRequest
67 голосов
/ 29 мая 2010

У меня есть простая программа, которая рисует предварительный просмотр Camera в SurfaceView. Я пытаюсь использовать метод onPreviewFrame, который вызывается каждый раз, когда в SurfaceView рисуется новый кадр, чтобы выполнить метод invalidate, который должен вызывать метод onDraw. , Фактически, вызывается метод onDraw, но там ничего не печатается (я полагаю, предварительный просмотр камеры переписывает текст, который я пытаюсь нарисовать).

Это упрощенная версия подкласса SurfaceView, которая у меня есть:

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

Ответы [ 3 ]

84 голосов
/ 29 мая 2010

SurfaceView, вероятно, не работает как обычный View в этом отношении.

Вместо этого сделайте следующее:

  1. Положите SurfaceView внутрь FrameLayout или RelativeLayout в XML-файл вашего макета, так как оба те позволяют складывать виджеты на ось Z
  2. Переместите логику рисования в отдельный кастом View класс
  3. Добавить экземпляр пользовательского просмотра класс для XML-файла макета в виде ребенок FrameLayout или RelativeLayout, но оно появилось после SurfaceView

Это приведет к тому, что ваш пользовательский класс View будет отображаться выше SurfaceView.

См. Здесь пример проекта , который размещает всплывающие панели над SurfaceView, используемым для воспроизведения видео.

17 голосов
/ 16 мая 2013

Попробуйте позвонить setWillNotDraw(false) с 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");
}

и вызов invalidate из onTouchEvent:

public boolean onTouch(View v, MotionEvent event) {

    invalidate();
    return true;
}
1 голос
/ 20 сентября 2011

Я думаю, вы должны сначала вызвать метод super.draw(), прежде чем делать что-либо в методе рисования SurfaceView.

...