Как нарисовать наложение на SurfaceView, используемое камерой на Android?
У меня есть простая программа, которая рисует предварительный просмотр 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);
}
}
Ответы
Ответ 1
SurfaceView
, вероятно, не работает как обычный View
в этом отношении.
Вместо этого выполните следующие действия:
- Поместите свой
SurfaceView
внутри
FrameLayout
или RelativeLayout
в
ваш XML файл макета, поскольку оба
они позволяют укладывать виджеты на
ось Z
- Переместите логику рисования
в отдельный пользовательский класс
View
- Добавить экземпляр пользовательского вида
класс в XML файл макета как
дочерний элемент
FrameLayout
или
RelativeLayout
, но если он появится
после SurfaceView
Это приведет к тому, что ваш пользовательский класс View
будет плавать над SurfaceView
.
См. здесь пример проекта, который отображает всплывающие панели выше SurfaceView
, используемые для воспроизведения видео.
Ответ 2
Попробуйте вызвать 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;
}
Ответ 3
Я думаю, вы должны сначала вызвать метод super.draw()
, прежде чем делать что-либо в методе рисования surfaceView.