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);
}
}
SurfaceView
は、おそらくこの点で通常のView
のようには機能しません。
代わりに、次を実行します。
SurfaceView
をレイアウトXMLファイルのFrameLayout
またはRelativeLayout
の内側に配置します。どちらもZ軸にウィジェットをスタックできるためです。View
クラスに移動しますFrameLayout
またはRelativeLayout
の子としてレイアウトXMLファイルに追加しますが、SurfaceView
の後に表示しますこれにより、カスタムView
クラスがSurfaceView
の上に浮いているように見えます。
サンプルプロジェクトについてはこちらをご覧ください ビデオ再生に使用されるSurfaceView
の上にポップアップパネルを重ねます。
surfaceCreated
からsetWillNotDraw(false)
を呼び出してみてください:
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;
}
SurfaceViewのdrawメソッドで何かを行う前に、最初にsuper.draw()
メソッドを呼び出す必要があると思います。