ビデオの最初と最後にある黒い surfaceView フラッシュを避けるために、@ tommyd と非常によく似たことをしなければならなくなりました。ただし、videoView のバックグラウンド ドローアブルの設定/無効化が、多くの電話で即座に行われないことがわかりました。背景を設定するための呼び出しと、実際に表示されるまでの間に約 0.5 秒の遅延が発生する可能性があります。
私が最終的にやったのは、単一の単色を表示するカスタム SurfaceView を作成し、これを VideoView の上に重ねて、SurfaceView.setZOrderMediaOverlay() を利用することでした。
私のカスタム SurfaceView は、http://android-er.blogspot.com/2010/05/android-surfaceview.html から多くの情報を得ました
。
public class SolidSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = SolidSurfaceView.class.getSimpleName();
private SolidSurfaceThread mThread;
private boolean mSurfaceIsValid;
private int mColor;
public SolidSurfaceView(Context context) {
super(context);
init();
}
public SolidSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SolidSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
Log.verbose(TAG, "init");
getHolder().addCallback(this);
setZOrderMediaOverlay(true);
}
public void setColor(int color) {
mColor = color;
invalidate();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.verbose(TAG, "surfaceCreated");
mSurfaceIsValid = true;
mThread = new SolidSurfaceThread(getHolder(), this);
mThread.setRunning(true);
mThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.verbose(TAG, "surfaceDestroyed");
mSurfaceIsValid = false;
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
}
catch (InterruptedException e) {
Log.warning(TAG, "Thread join interrupted");
}
}
mThread = null;
}
@Override
protected void onDraw(Canvas canvas) {
if ( ! mSurfaceIsValid) {
return;
}
canvas.drawColor(mColor);
}
private static class SolidSurfaceThread extends Thread {
private final SurfaceHolder mSurfaceHolder;
private final SolidSurfaceView mSurfaceView;
private boolean mIsRunning;
public SolidSurfaceThread(SurfaceHolder surfaceHolder, SolidSurfaceView surfaceView) {
mSurfaceHolder = surfaceHolder;
mSurfaceView = surfaceView;
}
public void setRunning(boolean running) {
mIsRunning = running;
}
@Override
public void run() {
while (mIsRunning) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
mSurfaceView.onDraw(c);
}
}
finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
そして、ビューをホストする親アクティビティで:
mVideoView = (VideoView)findViewById(R.id.video_view);
mVideoMask = (SolidSurfaceView)findViewById(R.id.video_mask);
mVideoMask.setColor(Color.BLUE);
mVideoMask.setVisibility(View.GONE)
その後、マスクを非表示にしたり、マスクを表示したりmVideoMask.setVisibility(View.VISIBLE)
(および黒い画面の VideoView を非表示にしたり)することができます。
さまざまな電話での私の実験では、この方法では、背景を設定/無効にするのではなく、ビデオ マスクを非常に高速に表示/非表示にできました。