天天看点

VideoView实现半屏全屏视频播放,自定义MediaView

本篇博客Demo链接:http://download.csdn.net/download/g_ying_jie/9960488

第一步、创建一个MediaView的xml布局,详见Demo的media_view.xml文件

第二步、创建MediaView类,直接继承Framelayout,并关联布局

public class MediaView extends FrameLayout implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, MediaPlayer.OnPreparedListener, View.OnTouchListener {

    private ImageView media_play;
    private ImageView media_fullscreen;
    private TextView media_total_time;
    private TextView media_current_time;
    private SeekBar media_seekBar;
    private MediaControllerListener listener;
    private VideoView videoView;
    private ProgressBar progressBar;
    private Context context;
    private RelativeLayout media_controller;
    private int progress;
    private boolean isHorizontal = false;
    private boolean fullscreen = false;
    private boolean isPause = false;

    private Timer timer;
    //间隔一秒更新一次SeekBar进度,SeekBar的max值取之于videoView.getDuration()
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1000:
                    if (videoView.isPlaying())
                        media_seekBar.setProgress(videoView.getCurrentPosition());
                    break;
            }
        }
    };


    public MediaView(@NonNull Context context) {
        super(context);
        loadRoot(context);
    }

    public MediaView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        loadRoot(context);
    }

    public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        loadRoot(context);
    }


    private void loadRoot(Context context) {
        this.context = context;
        View view = LayoutInflater.from(context).inflate(R.layout.media_view, this, true);
        initView(view);
    }

    private void initView(View view) {
        media_play = (ImageView) view.findViewById(R.id.media_play);
        media_play.setOnClickListener(this);
        media_fullscreen = (ImageView) view.findViewById(R.id.media_fullscreen);
        media_fullscreen.setOnClickListener(this);
        media_total_time = (TextView) view.findViewById(R.id.media_total_time);
        media_current_time = (TextView) view.findViewById(R.id.media_current_time);
        media_seekBar = (SeekBar) view.findViewById(R.id.media_seekbar);
        media_seekBar.setOnSeekBarChangeListener(this);
        progressBar = (ProgressBar) view.findViewById(R.id.media_pb);
        videoView = (VideoView) view.findViewById(R.id.media_video);
        videoView.setOnTouchListener(this);
        media_controller = (RelativeLayout) view.findViewById(R.id.media_controller);
    }   
}
           

第三步、添加监听的方法、开始播放的方法

public void setFullScreenListener(MediaControllerListener listener) {
        this.listener = listener;
    }

    public void start(String url) {
        videoView.setVideoURI(Uri.parse(url));
        videoView.setOnPreparedListener(this);
    }
           

第四步、在onPrepared中添加监听获取视频的宽高比,播放完成和开始播放回调。并开始播放视频

//视频加载完成
    @Override
    public void onPrepared(MediaPlayer mp) {
        if (progressBar != null && progressBar.isShown())
            progressBar.setVisibility(View.GONE);
        int[] time = getMinuteAndSecond(videoView.getDuration());
        media_seekBar.setMax(videoView.getDuration());
        media_total_time.setText(String.format("%02d:%02d", time[0], time[1]));

        starPlay();

        mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
            @Override
            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                //获取视频资源的宽度
                int mVideoWidth = mp.getVideoWidth();
                //获取视频资源的高度
                int mVideoHeight = mp.getVideoHeight();
                isHorizontal = mVideoWidth / mVideoHeight > 0 ? true : false;
            }
        });

        //播放完成
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                videoView.seekTo(0);
                media_seekBar.setProgress(0);
                media_play.setImageResource(R.mipmap.media_play);
            }
        });

        //开始播放
        mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
            @Override
            public boolean onInfo(MediaPlayer mp, int what, int extra) {
                if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
                    updateSeekBar();
                }
                return false;
            }
        });

    }
           

第五步、处理全屏播放切换,以及状态的回调

private void setFullScreen() {
        if (!fullscreen) {
            boolean playing = videoView.isPlaying();
            if (isHorizontal) {
                // 设置当前activity为横屏
                ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
            if (!playing) {
                videoView.pause();
            }
            //设置全屏模式
            hideSystemNavigationBar();
            media_fullscreen.setImageResource(R.mipmap.media_fullexit);
            listener.isFullScreen();
            fullscreen = true;
        } else {
            boolean playing = videoView.isPlaying();
            if (isHorizontal) {
                // 设置当前activity为竖屏
                ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
            if (!playing) {
                videoView.pause();
            }
            showSystemNavigationBar();
            media_fullscreen.setImageResource(R.mipmap.media_fullscreen);
            listener.isLittleScreen();
            fullscreen = false;
        }
    }
           
private void starPlay() {
        videoView.seekTo(progress);
        if (isPause)
            return;
        videoView.start();
        media_play.setImageResource(R.mipmap.media_pause);
    }
           

第六步、设置SeekBar进度条和VideoView的关联

//进度值改变
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int[] time = getMinuteAndSecond(progress);
        media_current_time.setText(String.format("%02d:%02d", time[0], time[1]));
    }

    //开始滑动
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        videoView.pause();
    }

    //停止滑动
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        videoView.seekTo(seekBar.getProgress());
        videoView.start();
        isPause = false;
        media_play.setImageResource(R.mipmap.media_pause);
    }
           

第七步、对外提供暂停和销毁的方法

public void onPause() {
        if (videoView.isPlaying()) {
            videoView.pause();
            media_play.setImageResource(R.mipmap.media_play);
        } else {
            isPause = true;
        }

        progress = videoView.getCurrentPosition();
        progressBar.setVisibility(VISIBLE);
        stopSeekBar();
    }

    public void onDestroy() {
        if (videoView != null) {
            videoView.stopPlayback();
        }
        stopSeekBar();
        handler.removeCallbacksAndMessages(null);
    }
           

第八步、状态栏、虚拟按键显隐的实现

private void hideSystemNavigationBar() {
        Window window = ((Activity) context).getWindow();
        if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) {
            View view = window.getDecorView();
            view.setSystemUiVisibility(View.GONE);
        } else if (Build.VERSION.SDK_INT >= 19) {
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            View decorView = window.getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }

    private void showSystemNavigationBar() {
        Window window = ((Activity) context).getWindow();
        if (Build.VERSION.SDK_INT >= 19) {
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        View decorView = window.getDecorView();
        decorView.setSystemUiVisibility(0);
    }
           

具体用法和案例在Demo中都有展示,有什么问题欢迎提出来交流