【问题标题】:VideoView onPrepared is not called if the VideoView is invisible如果 VideoView 不可见,则不会调用 VideoView onPrepared
【发布时间】:2014-02-15 11:23:47
【问题描述】:

我最初隐藏VideoView,当加载视频时,我显示VideoView。但是,如果 VideoView 最初是 invisible,则永远不会调用 onPrepared。但是,如果 VideoView 可见,则正确调用 onPrepared。有没有办法隐藏videoView,直到加载视频。任何帮助,将不胜感激。谢谢!

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);


            }
        });


}

【问题讨论】:

  • 你能解决这个问题吗?
  • @J.Kowalski 检查答案:)
  • 我用你原来的方法解决了这个问题,但是我做了让 videoview 不可见的布局,而不是 videoview 本身:)
  • 哦,太好了 :) 我应该在一开始就尝试过

标签: android video-streaming android-videoview


【解决方案1】:

更简单的解决方法:

只需为videoview 添加一个虚拟parentview,并为parentview 设置visiblity,而不是更改videoview 本身的visibility

【讨论】:

    【解决方案2】:

    解决了它使其布局不可见而不是 videoView 本身。 感谢@J.Kowalski。

    布局:

    <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"
        />
    

    设置 OnPreparedListener:

    videoView.setOnPreparedListener(this);
    

    在准备好之前显示进度条:

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

    加载视频 URI:

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

    当它准备好时,onPrepared 被调用:

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

    最后显示布局并开始视频:

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

    成功了!

    【讨论】:

      【解决方案3】:

      可以通过这些技巧之一来实现

      1. 您可以将VideoView的高度和宽度设置为1px,直到准备好视频,然后通过将属性更改为match parent来切换到全屏

      2. 正如@FDIM 在他的回答中所说,我们可以将视图的 alpha 值设置为 0,直到准备好视频。但它只有在我们使用TextureView 加载视频时才有效。它不适用于普通的VideoView。这是一个扩展 TextureView 的自定义 VideoView,它模仿了默认的 VideoVideo 实现。该类可以直接在xml文件中使用,可以设置alpha为0来隐藏视频。

        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) {
        
        }
        

      【讨论】:

        【解决方案4】:

        您可以尝试将视频视图的 alpha 通道设置为 0 或接近 0。

        【讨论】:

        • 此技巧仅在您使用TextureView 加载视频时有效。它不适用于普通的VideoView。无论如何感谢您的回答:)
        • 我使用 FrameLayout 作为视频视图的包装器,并将包装器 Alpha 设置为 0,然后将其 Visibility 设置为 Visible,并且在 onPreparedListener 内部将视频视图包装器的 alpha 返回到 1。 View.setAlpha仅从 API 11 开始可用。
        • 这里的Alpha是什么意思?我无法在整个上下文中理解 Alpha 这个词。
        • @MrNarendra 这只是不透明。看到这个:developer.android.com/reference/android/view/…
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多