Viewの重ね描きはaddContentViewで簡単にできるけど、SurfaceViewをオーバーレイしたい場合は一手間必要っぽいのでメモ。
OvlView.java
public class OvlView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder holder;
//コンストラクタ
public OvlView(Context context) {
super(context);
holder = this.getHolder();
holder.addCallback(this);
//ビューの背景を透過させる
getHolder().setFormat(PixelFormat.TRANSLUCENT);
//最前面に描画する
setZOrderOnTop(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = holder.lockCanvas();
//カンバスの背景を透明に(これじゃだめ)
//canvas.drawColor(Color.TRANSPARENT);
//描画例(円を描く)
Paint p = new Paint();
p.setARGB(255, 255, 0, 0);
p.setStyle(Paint.Style.STROKE);
canvas.drawCircle(300, 300, 300, p);
holder.unlockCanvasAndPost(canvas);
}
まずは、カンバスへの描画時に背景を「Color.TRANSPARENT」で透明にしようとしたが、これは効果なし。
<<<
(2014/12/2追記)
SurfaceViewの場合、カンバスの塗りつぶしを行わずに描画を重ねていくと古い描画が残ってしまうためアニメーションの場合(まあわざわざSurfaceView使うんだからアニメーション目的だよな、、)は上記は必要!
描画用メソッドの最初のほうで、以下の処理を行うべし。
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
>>>
解決策は、
setFormat(PixelFormat.TRANSLUCENT);
で、透過が実現され(translucentは半透明の意味なのがちょっと謎、、)、
setZOrderOnTop(true);
で、OvlViewを最前面に描画する(奥行き(z)軸のトップすなわち最前面にViewを割りこませるというイメージ?)。
注意点は、上記の処理をコンストラクタ呼び出し時点で行うこと。
最初、surfaceCreatedなどの描画時でおこなっていたら上手くいかなかった。
あとは、重ねられるビューにaddContentViewしてやれば完成。
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//オーバーレイビューの追加
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
addContentView(new OvlView(this), params);
}
}
ただ、この手法では通常のビューの重ね描きのように無制限にレイヤー数を重ねられるわけではなく、3枚程度が限度らしい(聞いただけで未確認)。