28

I am hiding the VideoView initially and when the video is loaded I am showing the VideoView. But onPrepared is never called if the VideoView is invisible initially. However onPrepared is called properly if VideoView is visible. Is there any way to hide the videoView until video is loaded. Any help would be appreciated. Thanks!

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >


<VideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:visibility="invisible" />

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        VideoView videoView = (VideoView) findViewById(R.id.video);
        Uri videoUri = Uri.parse(url);
        videoView.setVideoURI(videoUri);
        videoView.requestFocus();

        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                Toast.makeText(mActivity, "on prepared", Toast.LENGTH_SHORT).show();


                 videoView.setVisibility(View.VISIBLE);


            }
        });


}
Abhishek V
  • 12,488
  • 6
  • 51
  • 63

4 Answers4

12

You could try setting alpha channel of video view to 0 or close to 0.

FDIM
  • 1,981
  • 19
  • 21
  • 1
    This trick works only if you use [TextureView](http://developer.android.com/reference/android/view/TextureView.html) to load the video. It doesn't work with normal `VideoView`. Anyway thanks for the answer :) – Abhishek V May 23 '14 at 09:44
  • 3
    I used a FrameLayout as a wrapper for the video view and set the wrapper Alpha to 0 before setting its Visibility to Visible and inside the onPreparedListener return the video view wrapper's alpha back to 1. The View.setAlpha is only available since API 11. – LeoFarage Apr 13 '15 at 19:34
  • what do you mean by *Alpha* here? I am unable to understand the term `Alpha` in the whole context. – Narendra Singh Jul 03 '17 at 06:57
  • @MrNarendra It is just opacity. See this: https://developer.android.com/reference/android/view/View.html#setAlpha(float) – FDIM Jul 03 '17 at 17:21
5

Solved it making its layout invisible instead of videoView itself. Thanks to @J.Kowalski .

Layout:

<FrameLayout
    android:id="@+id/layout_video_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <VideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:scrollbars="none"/>
</FrameLayout>

<ProgressBar
    android:id="@+id/progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:visibility="gone"
    />

Set OnPreparedListener:

videoView.setOnPreparedListener(this);

Show progress bar before ready:

@Override
public void showProgress() {
    progress.setVisibility(View.VISIBLE);
    layoutVideoView.setVisibility(View.INVISIBLE);
}

Load video URI:

@Override
public void loadVideo(Uri uri) {
    videoView.setVideoURI(uri);
}

When its ready, onPrepared is called:

@Override
public void onPrepared(MediaPlayer mp) {
    Log.d("debug", "onPrepared");
    iStepPreviewPresenter.onVideoViewReady();
}

Finally show layout and start video:

@Override
public void hideProgress() {
    progress.setVisibility(View.INVISIBLE);
    layoutVideoView.setVisibility(View.VISIBLE);
}

@Override
public void startVideo() {
    videoView.start();
}

Nailed it!

Jiawei Dai
  • 604
  • 7
  • 6
4

It can be achieved by one of these tricks

  1. You can set the height and width of the VideoView to 1px until the video is prepared and then switch to full screen by changing the properties to match parent

  2. As @FDIM said in his answer, we can set the alpha value of the view to 0 until video is prepared. But it works only if we use TextureView to load the video. It doesn't work with normal VideoView. Here is a custom VideoView extending TextureView which mimics the default VideoVideo implementation. This class can be directly used in xml file and can set the alpha to 0 to hide the video.

    public class TextureVideoView extends TextureView  implements SurfaceTextureListener                {
    
    private MediaPlayer mMediaPlayer;
    
    public TextureVideoView(Context context) {
        super(context);
        init();
    }
    
    public TextureVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    private void init() {
        mMediaPlayer = new MediaPlayer();
        this.setSurfaceTextureListener(this);
    }
    
    public void seekTo(int msec) {
        mMediaPlayer.seekTo(msec);
    }
    
    public void setVideoPath(final String path) throws IOException {
        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(path);
        mMediaPlayer.prepare();
    }
    
    public void setVideoPath(FileDescriptor fd, long offset, long length) throws IOException {
        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(fd, offset, length);
        mMediaPlayer.prepare();
    }
    
    public void setVideoURI(Context context, Uri uri) throws IOException {
        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(context, uri);
    }
    
    public void setOnPreparedListener(OnPreparedListener onPreparedListener) {
        mMediaPlayer.setOnPreparedListener(onPreparedListener);
    }
    
    public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
        mMediaPlayer.setOnCompletionListener(onCompletionListener);
    }
    
    public void setOnErrorListener(OnErrorListener onErrorListener) {
        mMediaPlayer.setOnErrorListener(onErrorListener);
    }
    
    public void start() {
        mMediaPlayer.start();
    }
    
    public void pause() {
        mMediaPlayer.pause();
    }
    
    public void setVolume(float leftVolume, float rightVolume ) {
        mMediaPlayer.setVolume(leftVolume, rightVolume);
    }
    
    public boolean isPlaying() {
        return mMediaPlayer.isPlaying();
    }
    
    public void stopPlayback() {
        mMediaPlayer.stop();
    }
    
    public void reset() {
        mMediaPlayer.reset();
    }
    
    public void release() {
        mMediaPlayer.release();
    }
    
    
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
            int height) {
    
        mMediaPlayer.setSurface(new Surface(surface));
    }
    
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }
    
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
            int height) {
    
    }
    
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    
    }
    
Abhishek V
  • 12,488
  • 6
  • 51
  • 63
0

An easier workaround:

Just add a dummy parentview for the videoview and set the visiblity for that parentview instead of changing the visibility of the videoview itself.

Thiagesh thg
  • 100
  • 7