VideoView black flash before and after playing

前端 未结 14 2219
谎友^
谎友^ 2020-12-09 04:04

I have a VideoView which I want to use to play a movieclip. I use it like this to play it and it works.

VideoView vv = new VideoView(this);
vv.setVideoURI(Ur         


        
14条回答
  •  轮回少年
    2020-12-09 04:40

    I ended up having to do something very similar to @tommyd to avoid the black surfaceView flash at the beginning and end of my videos. However, I found that setting/nulling the background drawable for the videoView was not occurring instantly on many phones. There could be about a half-second delay between my call to set the background and when it was actually displayed.

    What I ended up doing was creating a custom SurfaceView that showed a single, solid color, then overlayed this on top of the VideoView and made use of SurfaceView.setZOrderMediaOverlay().

    My custom SurfaceView was heavily informed by: 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);
                        }
                    }
                }
            }
        }
    }
    

    And in the parent activity that hosts the views:

        mVideoView = (VideoView)findViewById(R.id.video_view);
        mVideoMask = (SolidSurfaceView)findViewById(R.id.video_mask);
        mVideoMask.setColor(Color.BLUE);
    

    You can then do things like mVideoMask.setVisibility(View.GONE) to hide the mask or mVideoMask.setVisibility(View.VISIBLE) to show the mask (and hide the black-screened VideoView).

    In my experiments on various phones, this method provided very fast showing/hiding of the video mask, as opposed to setting/nulling the background.

提交回复
热议问题