Android VideoView 视频播放器 仿抖音
2020-07-12 16:21
351 查看
前言
最近项目有个需求 , 做个类似抖音的视频效果. 又因为包大小的问题不使用第三方SDK,所以使用原生的VideoView开发了一下, 搭配RecyclerView和PageSnapHelper来实现抖音的效果.
全部代码: github
看一下实现流程:
首先创建了一个继承自ConstraintLayout的View,用来实现自己的布局.东西不多, 里面主要是播放控制的按钮, 和一个可以拖动的进度条.在视频加载成功之前显示一个封面图.
然后创建了一个State的enum类:
public enum VideoState { unKnow, loadFinish, playing, playEnd, error, pause }
这是主要是用于在视频进度有变化的时候用来保存一下状态 .
之后创建了一个handler , 用于实时更新进度条,以及已播放的时间.
@SuppressLint("HandlerLeak") private final Handler mHandler = new Handler() { @SuppressLint("SetTextI18n") @Override public void handleMessage(Message msg) { if (msg.what == UPDATE_PROGRESS) { if (videoView.isPlaying()) { int currentTime = videoView.getCurrentPosition(); if (currentTime >= mDuration) { videoView.seekTo(0); seekBarProgress.setProgress(0); alreadyTextView.setText("00:00"); mHandler.removeMessages(UPDATE_PROGRESS); } else { seekBarProgress.setProgress(currentTime); mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 500); alreadyTextView.setText(TimeUtil.formatTimeWhichExist(currentTime)); } } } } };
然后实现一个SeekBar 的监听 ,
3个函数分别是:
- OnSeekBarChangeListener: 进度条有改变
- onStartTrackingTouch 手指按下进度条
- onStopTrackingTouch 手指离开进度条
private SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { alreadyTextView.setText(TimeUtil.formatTimeWhichExist(progress)); if (mOnProgressChangedListener != null) { mOnProgressChangedListener.onProgressChanged(progress); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { // 暂停刷新 mHandler.removeMessages(UPDATE_PROGRESS); } @Override public void onStopTrackingTouch(SeekBar seekBar) { int progress = seekBar.getProgress(); if (videoView != null) { if (progress + 1000 < mDuration) { // 设置当前播放的位置 videoView.seekTo(progress); mHandler.sendEmptyMessage(UPDATE_PROGRESS); } else { mVideoState = VideoState.playEnd; start(); } } } };
在按下的时候 , 停止跟随视频进度改变, 离开时 , 从当前位置继续播放.
但是视频是有关键帧的, 所以可能会跳到前一个关键帧的位置播放.
在进度有改变的时候, 实时改变已播放的时间的textview.
在播放器初始化的时候, 监听一下视频播放.
- setOnPreparedListener 是去加载视频 , 有一个加载完成时的回调, 这里在加载完成时, 隐藏封面并开始播放.
- setOnCompletionListener 是播放完成时的回调,此时改变进度并重新播放视频.
- setOnErrorListener 是视频播放出错的回调
videoView.setOnPreparedListener(mp -> { mVideoState = VideoState.loadFinish; mHandler.sendEmptyMessage(UPDATE_PROGRESS); totalPlayTextView.setText(Util.formatTimeWhichExist(mDuration)); videoThumb.setVisibility(GONE); start(); }); videoView.setOnCompletionListener(mp -> { mHandler.removeMessages(UPDATE_PROGRESS); mVideoState = VideoState.playEnd; changePlayIcon(); seekBarProgress.setProgress(0); alreadyTextView.setText("00:00"); videoThumb.setVisibility(VISIBLE); }); videoView.setOnErrorListener((mp, what, extra) -> { //异常回调 mVideoState = VideoState.error; return false; });
之后定义了一些操控视频的方法 , 像播放,暂停,获取播放进度等等的public方法, 用来给外界调用.
public void start() { if (mVideoState == VideoState.playEnd) { videoView.resume(); } else { videoView.start(); } mVideoState = VideoState.playing; changePlayIcon(); mHandler.sendEmptyMessage(UPDATE_PROGRESS); } public void pause() { videoView.pause(); mVideoState = VideoState.pause; changePlayIcon(); } public void stop() { videoView.stopPlayback(); mHandler.removeMessages(UPDATE_PROGRESS); } public void setVideoVisible() { controllerLayout.setVisibility(VISIBLE); } public void setVideoGone() { controllerLayout.setVisibility(GONE); } public VideoState getState() { if (videoView.isPlaying()) { mVideoState = VideoState.playing; } return mVideoState; } public int getCurrentPosition() { return videoView.getCurrentPosition(); }
设置视频数据:
public void setVideo(VideoInfo video) { try { videoView.setVideoURI(Uri.parse(video.getUrl())); mDuration = (int) video.getDuration(); seekBarProgress.setMax(mDuration); start(); //宽高比 int width = video.getWidth(); int height = video.getHeight(); float aspectRatio = (float) width / height; ConstraintLayout.LayoutParams layoutParamsThumb = (ConstraintLayout.LayoutParams) videoThumb.getLayoutParams(); //取控件textView当前的布局参数 setLayoutParam(layoutParamsThumb, aspectRatio); videoThumb.setLayoutParams(layoutParamsThumb); } catch (Throwable ignore) { } }
这里是播放的网络视频, 所以传进来的是一个url , 并且根据宽高比显示封面图 , 使其和视频的位置和大小是一致的.
其他代码应该都不需要介绍了, 详细了解可以看看github
相关文章推荐
- Android多媒体开发【2】-- 利用VideoView开发最简单的视频播放器
- Android开发06_VideoView、SurfaceView两种视频播放器
- android 视频播放器 android videoView 按不同比例缩放
- Android-SurfaceView+VideoView视频播放器实例
- Android中关于ScrollView中有视频播放器VideoView时问题的总结
- Android 视频播放器 VideoView 的使用,播放本地视频 和 网络 视频
- android使用VideoView设计的扫描全局.mp4和.3gp的视频播放器
- Android多媒体开发【2】-- 利用VideoView开发最简单的视频播放器
- Android:利用VideoView实现视频播放器
- Android 视频播放器VideoView
- Android 视频播放器 VideoView 的使用,播放本地视频 和 网络 视频
- Android 视频播放器 VideoView 的使用,播放本地视频 和 网络 视频,androidvideoview
- android 视频播放器 android videoView 按不同比例缩放 .
- android关于VideoView或Vitamio视频播放器横竖屏切换
- Android 视频播放器 VideoView 的使用,播放本地视频 和 网络视频
- android_视频播放器(VideoView)
- Android视频播放项目总结之 使用VideoView定义自己的视频播放器
- Android 多媒体应用:视频播放之VideoView与SurfaceView
- Android使用VideoView播放网络视频
- Android那些事 - VideoView使用总结