一、开篇唠嗑:谁还没被视频播放坑过?
还记得第一次在Android里搞视频播放的血泪史吗?对着MediaPlayer手写状态机,结果进度条比蜗牛还慢,声音画面玩起二人转…(此处应有捂脸表情)直到遇见VideoView——这个被官方塞进安卓工具箱的“懒人救星”,我才发现原来播视频可以像点奶茶一样简单!今天咱们就用打游戏刷副本的姿势,把它扒得底裤都不剩!
二、VideoView是何方神圣?
👉 官方人设:表面看是个能塞进布局的视频播放框,实际是MediaPlayer+SurfaceView的“私生子”!
👉 隐藏技能:
- 自动处理预加载、缓冲进度(再不用手写Loading圈)
- 内置播放/暂停/进度拖拽三件套(省掉50行控制代码)
- 支持MP4/3GP等主流格式(但遇到MKV请自觉转码)
重点来了:它本质上是个带着播放器灵魂的View!这意味着你既能当普通控件摆弄,又能直接调用start()、pause()等骚操作,堪称安卓界的“瑞士军刀”。
三、实战开始:从零搭建播放器(附可复制代码)
步骤1:在布局文件里挖个“视频坑”
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#000" />
⚠️ 注意:高度别写wrap_content!视频源尺寸参差不齐,容易引发布局坍塌惨案~
步骤2:在Activity里注入灵魂
class MainActivity : AppCompatActivity() {
private lateinit var videoView: VideoView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 绑定控件
videoView = findViewById(R.id.videoView)
// 设置视频路径(三种姿势任选)
// 姿势1:播放本地文件
val uri = Uri.parse("android.resource://${packageName}/${R.raw.demo}")
// 姿势2:播放网络视频
// val uri = Uri.parse("https://xxx.com/demo.mp4")
// 姿势3:播放SD卡视频
// val uri = Uri.fromFile(File("/sdcard/Movies/demo.mp4"))
videoView.setVideoURI(uri)
// 绑定媒体控制器(出现神秘控制条!)
videoView.setMediaController(MediaController(this))
// 设置准备完成监听(避免黑屏尴尬)
videoView.setOnPreparedListener {
videoView.start()
Toast.makeText(this, "视频开始飙车啦!", Toast.LENGTH_SHORT).show()
}
// 设置播放完成回调
videoView.setOnCompletionListener {
Toast.makeText(this, "播完了,要不来个循环?", Toast.LENGTH_SHORT).show()
}
}
}
步骤3:别忘了在AndroidManifest.xml开权限!
<!-- 如果需要播放网络视频 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 如果需要读取SD卡 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
四、深度飙车技巧:让播放器更懂人心
场景1:实现“秒开播放”
在setOnPreparedListener里藏个黑科技:
videoView.setOnPreparedListener { mp ->
mp.setOnBufferingUpdateListener { _, percent ->
// 当缓冲超过30%立即播放,拒绝转圈等待
if (percent > 30 && !videoView.isPlaying) {
videoView.start()
}
}
}
场景2:应对生命周期暴击
在onPause()和onResume()里安排后事:
override fun onPause() {
super.onPause()
// 记录播放位置并暂停
videoView.pause()
}
override fun onResume() {
super.onResume()
// 偷懒方案:直接续播(复杂场景建议用seekTo定位)
videoView.start()
}
场景3:自定义控制条(高能玩法)
嫌弃系统控制条太丑?自己造个!
// 1. 隐藏系统控制器
videoView.setMediaController(null)
// 2. 在布局底部放自定义控制栏(包含播放/进度条/全屏按钮)
// 3. 手动绑定事件
btn_play.setOnClickListener {
if(videoView.isPlaying) videoView.pause() else videoView.start()
}
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if(fromUser) videoView.seekTo(progress * videoView.duration / 100)
}
})
五、填坑指南:那些年我们踩过的雷
雷区1:网络视频加载慢
解决方案:
- 用VideoView的setOnInfoListener监听MEDIA_INFO_BUFFERING_START/END
- 缓冲时显示ProgressDialog,结束后隐藏
雷区2:切换横竖屏被重置
在AndroidManifest里给Activity加锁:
android:configChanges="orientation|screenSize"
雷区3:内存泄漏
记住三大纪律:
- onDestroy中调用videoView.stopPlayback()
- 移除所有监听器
- 避免在RecyclerView的Item里直接使用VideoView(血的教训!)
六、扩展脑洞:VideoView还能这么玩
- 实现小窗播放:用WindowManager把VideoView挂到桌面上
- 视频轮播器:多个VideoView+ViewPager2打造抖音式体验
- 蒙版特效:给VideoView覆盖半透明PNG实现异形播放框
七、结语
VideoView就像Android世界的乐高积木——看似简单但组合空间无限!从今天起别再复制粘贴老代码,用这些姿势解锁播放器新境界。
1万+

被折叠的 条评论
为什么被折叠?



