在Android上播放视频最简单的方法是使用SDK中内置的VideoView,然后加上MediaController来控制视频播放暂停等,但是这样有一个缺点是无法定制自己的控制UI,所以这里提供一个自定义播放控件,它可以设置多种自定义属性(如loading样式,错误视频等),并且很容易在全屏与非全屏之间切换,另外支持Android V2.3及以上系统.

项目地址: https://github.com/linsea/UniversalVideoView

1. 在build.gradle文件上加入以下依赖包.

dependencies {compile 'com.linsea:universalvideoview:1.1.0@aar'}

2. 在布局文件中加入自定义View,注意要使UniversalVideoView和UniversalMediaController位于同一个父Layout中, 这样控制条才会浮在视频之上.

<FrameLayoutandroid:id="@+id/video_layout"android:layout_width="fill_parent"android:layout_height="200dp"android:background="@android:color/black"><com.universalvideoview.UniversalVideoViewandroid:id="@+id/videoView"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_gravity="center"app:uvv_autoRotation="true"app:uvv_fitXY="false" /><com.universalvideoview.UniversalMediaControllerandroid:id="@+id/media_controller"android:layout_width="fill_parent"android:layout_height="fill_parent"app:uvv_scalable="true" /></FrameLayout>

3. 在onCreate方法中设置相关事件的监听.

View mBottomLayout;
View mVideoLayout;
UniversalVideoView mVideoView;
UniversalMediaController mMediaController;mVideoView = (UniversalVideoView) findViewById(R.id.videoView);
mMediaController = (UniversalMediaController) findViewById(R.id.media_controller);
mVideoView.setMediaController(mMediaController);mVideoView.setVideoViewCallback(new UniversalVideoView.VideoViewCallback() {@Overridepublic void onScaleChange(boolean isFullscreen) {this.isFullscreen = isFullscreen;if (isFullscreen) {ViewGroup.LayoutParams layoutParams = mVideoLayout.getLayoutParams();layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;mVideoLayout.setLayoutParams(layoutParams);//设置全屏时,无关的View消失,以便为视频控件和控制器控件留出最大化的位置mBottomLayout.setVisibility(View.GONE);} else {ViewGroup.LayoutParams layoutParams = mVideoLayout.getLayoutParams();layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = this.cachedHeight;mVideoLayout.setLayoutParams(layoutParams);mBottomLayout.setVisibility(View.VISIBLE);}}@Overridepublic void onPause(MediaPlayer mediaPlayer) { // 视频暂停Log.d(TAG, "onPause UniversalVideoView callback");}@Overridepublic void onStart(MediaPlayer mediaPlayer) { // 视频开始播放或恢复播放Log.d(TAG, "onStart UniversalVideoView callback");}@Overridepublic void onBufferingStart(MediaPlayer mediaPlayer) {// 视频开始缓冲Log.d(TAG, "onBufferingStart UniversalVideoView callback");}@Overridepublic void onBufferingEnd(MediaPlayer mediaPlayer) {// 视频结束缓冲Log.d(TAG, "onBufferingEnd UniversalVideoView callback");}});

注意:
UniversalVideoView 没有保存播放的状态,如播放到第几分钟了,所以需要应用自己保存这些状态并恢复.
如果为了避免在旋转屏幕时系统重启Activity,需要添加Activity的属性:

android:configChanges="orientation|keyboardHidden|screenSize

4 定制属性

为了保证定制UI的灵活度,提供以下属性:

uvv_fitXY

UniversalVideoView的属性,布尔值,true时设置视频缩放时在X,Y方向上铺满View设置的宽度和高度,这样可能使视频变形.false时则缩放时保持视频的长宽比例,与SDK中的VideoView类似.

uvv_autoRotation

UniversalVideoView的属性,布尔值,true时视频会根据重力响应通知客户进行全屏与非全屏之间的切换.

uvv_scalable

UniversalMediaController属性,布尔值,是否显示控制条右下方的缩放按钮,如果不想全屏播放时,可以设置为false不显示.

5、在AndroidManifest.xml添加配置

权限:<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />activity属性:android:configChanges="orientation|keyboardHidden|screenSize"

6、在activity中展示

public class MainActivity extends AppCompatActivity implements UniversalVideoView.VideoViewCallback {private View videoLayout;private View bottomLayout;private UniversalVideoView videoView;private UniversalMediaController mediaController;private int seekPosition;//当前进度private int cachedHeight;//视频区域大小private boolean isFullscreen;//是否全屏private static final String VIDEO_URL = "http://vf1.mtime.cn/Video/2017/03/15/mp4/170315222409670447.mp4";private static final String SEEK_POSITION_KEY = "SEEK_POSITION_KEY";//用于保存seekPosition的key值@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();intiEvent();}/*** 初始化控件*/private void initView() {videoLayout = findViewById(R.id.videoLayout);bottomLayout = findViewById(R.id.bottomLayout);videoView = (UniversalVideoView) findViewById(R.id.videoView);mediaController = (UniversalMediaController) findViewById(R.id.mediaController);}
private void intiEvent() {//把视频控制的按钮设置到播放器里videoView.setMediaController(mediaController);//设置置视频区域大小setVideoAreaSize();//设置屏幕状态和播放状态的监听videoView.setVideoViewCallback(this);}/*** 设置置视频区域大小和播放地址*/private void setVideoAreaSize() {videoLayout.post(new Runnable() {@Overridepublic void run() {int width = videoLayout.getWidth();cachedHeight = (int) (width * 405f / 720f);// cachedHeight = (int) (width * 3f / 4f);// cachedHeight = (int) (width * 9f / 16f);ViewGroup.LayoutParams videoLayoutParams = videoLayout.getLayoutParams();videoLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;videoLayoutParams.height = cachedHeight;videoLayout.setLayoutParams(videoLayoutParams);videoView.setVideoPath(VIDEO_URL);videoView.requestFocus();
}});}/**
* 开始按钮
*
* @param v
*/public void startClick(View v) {//设置视频开始videoView.start();//设置视频标题mediaController.setTitle("寻梦环游记");}
//--------------重写下面三个方面是为了保存seekPosition--------------@Overrideprotected void onPause() {super.onPause();if (videoView != null && videoView.isPlaying()) {seekPosition = videoView.getCurrentPosition();Log.i("info", "onPause mSeekPosition=" + seekPosition);videoView.pause();}}@Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);Log.i("info", "onSaveInstanceState Position=" + videoView.getCurrentPosition());outState.putInt(SEEK_POSITION_KEY, seekPosition);}@Overrideprotected void onRestoreInstanceState(Bundle outState) {super.onRestoreInstanceState(outState);seekPosition = outState.getInt(SEEK_POSITION_KEY);Log.i("info", "onRestoreInstanceState Position=" + seekPosition);}//--------------以下方法都是VideoViewCallback接口的实现方法--------------/**
* 全屏和默认的切换
*
* @param isFullscreen
*/@Overridepublic void onScaleChange(boolean isFullscreen) {this.isFullscreen = isFullscreen;if (isFullscreen) {ViewGroup.LayoutParams layoutParams = videoLayout.getLayoutParams();layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;videoLayout.setLayoutParams(layoutParams);//设置全屏时,无关的View消失,以便为视频控件和控制器控件留出最大化的位置bottomLayout.setVisibility(View.GONE);} else {ViewGroup.LayoutParams layoutParams = videoLayout.getLayoutParams();layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;layoutParams.height = this.cachedHeight;videoLayout.setLayoutParams(layoutParams);bottomLayout.setVisibility(View.VISIBLE);}switchTitleBar(!isFullscreen);}/**
* 横竖屏切换的时候控制ActionBar的状态
*
* @param show
*/private void switchTitleBar(boolean show) {android.support.v7.app.ActionBar supportActionBar = getSupportActionBar();if (supportActionBar != null) {if (show) {supportActionBar.show();} else {supportActionBar.hide();}}}@Overridepublic void onPause(MediaPlayer mediaPlayer) {// 视频暂停Log.i("info", "onPause");}@Overridepublic void onStart(MediaPlayer mediaPlayer) {// 视频开始播放或恢复播放Log.i("info", "onStart");}@Overridepublic void onBufferingStart(MediaPlayer mediaPlayer) {// 视频开始缓冲Log.i("info", "onBufferingStart");}@Overridepublic void onBufferingEnd(MediaPlayer mediaPlayer) {// 视频结束缓冲Log.i("info", "onBufferingEnd");}@Overridepublic void onBackPressed() {if (this.isFullscreen) {videoView.setFullscreen(false);} else {super.onBackPressed();}}}

UniversalVideoView相关推荐

  1. Android UniversalVideoView视频播放器

    1.添加依赖 app下的 build.gradle dependencies {......compile 'com.linsea:universalvideoview:1.1.0@aar' } 2. ...

  2. Android 视频播放器,在线播放

    1. Bilibili https://github.com/Bilibili/ijkplayer 1.测试的时候总是崩溃,不知道是我不会用还是怎么回事. 2016-04-15 2.AndroidVi ...

  3. 强大的第三方视频播放器。

    近来静极思动,决定写一堆博客. 没别的意思,单纯的想**** //小白使用文档 https://shimo.im/docs/xj5F85W1gqEEBXRJ https://shimo.im/docs ...

  4. Android 开源项目分类汇总(下)

    Android 开源项目分类汇总(下) 九.ScrollView Discrollview 支持滚动时 Item 淡入淡出,平移,缩放效果的 ScrollView 项目地址:https://githu ...

  5. Android github上优秀开源项目分类汇总

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  6. Android 开源项目分类汇总(很全)

    目录 前言 目前包括: 第一部分 个性化控件(View) 一.ListView 二.ActionBar 三.Menu 四.ViewPager .Gallery 五.GridView 六.ImageVi ...

  7. Android系统(168)---Android 开源项目分类汇总

    Android开源项目分类汇总 原网址:https://blog.csdn.net/prince77qiqiqq/article/details/51338330 Android 开源项目第一篇--个 ...

  8. github上Android开源项目汇总(带效果图)

    第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ...

  9. [转]Android 开源项目分类汇总

    Android 开源项目分类汇总,更全更新可见 codekk.com Other: English Version, 繁體版, Website Version. 我们的微信公众号:codekk.二维码 ...

最新文章

  1. 分析Windows和Linux动态库
  2. 1.7 截取(提取)子字符串(substring())
  3. pci驱动与硬件通信
  4. new LayoutParams 使用
  5. vb treeview 展开子节点_详解最长公共子序列问题,秒杀三道动态规划题目
  6. springboot mysql时区设置_java/springboot/mysql时区问题解决方案
  7. 【牛客 - 370E】Rinne Loves Gift(Bellman_Ford判负环,二分,分数规划)
  8. 【网络基础】【TCP/IP】私有IP地址段
  9. 能打开java文件的软件有哪些_使用JAVA打开本地应用程序相关的文件
  10. 打鱼晒网c语言用switch语句,三天打鱼两天晒网题目的C++源代码.docx
  11. 基于Java+Springboot+Vue+elememt宠物用品商城系统设计实现
  12. TF_REPEATED_DATA ignoring data with redundant timestamp for frame left_wheel at time
  13. 无效的月份oracle,Oracle插入失败:无效的月份
  14. TO B是什么?TO C呢?
  15. IDEA的ultimate(最终版)与community(社区版)的区别?
  16. 小米公司2021秋招面试题目整理
  17. 国防科技大学计算机学院 网络与信息安全研究所所长,为网络铸盾,国防科大战队再获佳绩!...
  18. SS54/SS24/SS510及SMA/SMB/SMC不同封装区别
  19. 基于java的题库管理系统
  20. 如何在Springboot实现条件查询

热门文章

  1. MongoDB初试备份及恢复
  2. delphi.指针.应用----应用重要 多看 多练
  3. BZOJ2424 [HAOI2010]订货
  4. 音响上的英文是什么意思_鞋盒上的字母后缀 是什么意思?(上)
  5. java中key的作用_key word ‘final’ 在java 中作用
  6. 微信公众号自动回复html,[.NET] 简单接入微信公众号开发:实现自动回复
  7. python 数组 元组 列表_python_Day_02[数组、列表、元组之篇]
  8. 2021柳州市地区高考成绩排名查询,2021年柳州所有高中排名一览表
  9. java预览表格预览文档_java 如何创建一个表格.docx
  10. 三层调用关系_你真正的了解MVC三层架构开发模式吗