由于项目需求,项目主页面有很多个page页面,每个page页面中都有一个VideoView用于播放视频,写次demo用来练手。
源码下载地址
由于4个page页面的内容一样,所以看起来不好区分,但是功能还是实现了,将就着吧。
2、分析代码:
定义MainActivity.java内部的全局变量:
ViewPager mViewPager;
MyPagerAdapter mAdapter;
/*** 本地视频路径 ***/
String path = Environment.getExternalStorageDirectory().getPath()
+ "/Test.mp4";
// /*** 网络视频路径 ***/
// String path =
// "http://";
/*** 视频路径集合 ***/
String[] paths = new String[] { path, path, path, path };
/*** viewpager的根视图数据集合 ***/
List mViewList;
/*** 当前页面索引 ***/
int currentItem = 0;
/*** 上一个页面索引 ***/
int lastItem = 0;
/*** 页面的视频控件集合 ***/
static List mVideoViewList;
/*** 页面播放进度控制器集合 ***/
static List mMediaControllerList;
/*** 页面视频缓冲图集合 ***/
static List mCacheViewList;
/*** 记录每个page页面视频播放的进度 ***/
static Map mCurrentPositions;
/*** 记录每个page页面的视频播放状态 ***/
static Map mIsPlaying;
// static Map mIsPageFirstAvaliable;// 记录每个page页面是否第一次加载
然后在oncreate方法中初始化数据:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) this.findViewById(R.id.mViewPager);
initializeData();
Log.e(Tag, "onCreate-------->");
}
initializeData()方法如下:
private void initializeData() {
mViewList = new ArrayList();
mVideoViewList = new ArrayList();
mMediaControllerList = new ArrayList();
mCacheViewList = new ArrayList();
mCurrentPositions = new HashMap();
mIsPlaying = new HashMap();
// mIsPageFirstAvaliable = new HashMap();
for (int i = 0; i < paths.length; i++) {
ViewGroup v = (ViewGroup) View.inflate(this, R.layout.page_layout,
null);
VideoView vv = (VideoView) v.findViewById(R.id.mVideoView);
View mView = (View) v.findViewById(R.id.mView);
MediaController mpc = new MediaController(this);
vv.setVideoPath(paths[i]);// 本地视频
// vv.setVideoURI(Uri.parse(path));// 网络视频
vv.setMediaController(mpc);
setListener(vv);
mViewList.add(v);
mVideoViewList.add(vv);
mMediaControllerList.add(mpc);
mCacheViewList.add(mView);
mCurrentPositions.put(i, 0);// 每个页面的初始播放进度为0
mIsPlaying.put(i, true);// 每个页面的初始播放状态false
// mIsPageFirstAvaliable.put(i, true);// 每个页面默认第一次
}
mAdapter = new MyPagerAdapter(this, mViewList);
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(this);
if (mVideoViewList.get(0) != null) {
mVideoViewList.get(0).start();
mIsPlaying.put(0, true);
// mIsPageFirstAvaliable.put(0, false);
}
}
setlistener方法:
private void setListener(VideoView vv) {
vv.setOnInfoListener(this);
vv.setOnCompletionListener(this);
vv.setOnErrorListener(this);
vv.setOnPreparedListener(this);
}
viewpager的适配器MyPagerAdapter :
class MyPagerAdapter extends android.support.v4.view.PagerAdapter {
Context context;
List mViewList;
public MyPagerAdapter(Context context, List list) {
this.context = context;
this.mViewList = list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mViewList != null ? mViewList.size() : 0;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == (View) arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
// super.destroyItem(container, position, object);
container.removeView(mViewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(mViewList.get(position));
return mViewList.get(position);
}
}
页面滑动时,需要对视频播放进行记录,并更改页面播放状态,操作放在滑动结束后:
@Override
public void onPageSelected(int pageIndex) {
lastItem = currentItem;
currentItem = pageIndex;
// Log.e(Tag, "currentItem: " + currentItem);
if (mVideoViewList.get(lastItem) != null) {
if (mVideoViewList.get(lastItem).isPlaying()) {
mIsPlaying.put(lastItem, true);// 记录播放状态
mVideoViewList.get(lastItem).pause();
} else {
mIsPlaying.put(lastItem, false);// 记录播放状态
}
mCurrentPositions.put(lastItem, mVideoViewList.get(lastItem)
.getCurrentPosition());// 记录播放进度
}
if (mMediaControllerList.get(lastItem) != null) {
if (mMediaControllerList.get(lastItem).isShowing()) {
mMediaControllerList.get(lastItem)
.setVisibility(View.INVISIBLE);
}
}
if (mVideoViewList.get(currentItem) != null) {
// 如果页面第一次加载
// if (mIsPageFirstAvaliable.get(currentItem)) {
// mIsPlaying.put(currentItem, true);
// mIsPageFirstAvaliable.put(currentItem, false);
// } else {
// 不是第一次加载跳到当前播放进度
mVideoViewList.get(currentItem).seekTo(
mCurrentPositions.get(currentItem));
// }
if (mIsPlaying.get(currentItem)) {
mVideoViewList.get(currentItem).start();
}
mMediaControllerList.get(currentItem).show(1000);
}
}
当activity失去焦点,停止时也需要进行记录操作:
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if (mVideoViewList.get(currentItem) != null) {
if (mVideoViewList.get(currentItem).isPlaying()) {
mIsPlaying.put(currentItem, true);
mVideoViewList.get(currentItem).pause();
} else {
mIsPlaying.put(currentItem, false);
}
mCurrentPositions.put(currentItem, mVideoViewList.get(currentItem)
.getCurrentPosition());
}
}
activity销毁时,要清空数据集合,释放内存资源:
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mVideoViewList.get(currentItem) != null) {
mVideoViewList.get(currentItem).stopPlayback();
mVideoViewList.get(currentItem).suspend();
}
clearList();
Log.e(Tag, "onDestroy-------->");
}
/**
* 清空static数据
*/
private void clearList() {
mVideoViewList.clear();
mMediaControllerList.clear();
mCacheViewList.clear();
mCurrentPositions.clear();
mIsPlaying.clear();
}
在界面重新对用户可见时,根据记录的播放进度设置进度再判断是否播放:
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if (mVideoViewList.get(currentItem) != null) {
mVideoViewList.get(currentItem).seekTo(
mCurrentPositions.get(currentItem));
if (mIsPlaying.get(currentItem)) {
mVideoViewList.get(currentItem).start();
}
}
}
另外,还需要给videoview设置相应的监听器,监听器都需要实现各自的方法:
@Override
//播放完成监听:
public void onCompletion(MediaPlayer mp) {
if (mVideoViewList.get(currentItem) != null) {
mCurrentPositions.put(currentItem, 0);// 重新播放,进度重置为0
mIsPlaying.put(currentItem, true);// 播放状态:正在播放
mVideoViewList.get(currentItem).resume();
mVideoViewList.get(currentItem).start();
}
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(View.VISIBLE);
}
} else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
// 此接口每次回调完START就回调END,若不加上判断就会出现缓冲图标一闪一闪的卡顿现象
if (mp.isPlaying()) {
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(
View.INVISIBLE);
}
}
}
return true;
}
//播放出错监听
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
// 这里设置为true防止弹出对话框,屏蔽原始出错的处理
return true;
}
//准备完成监听
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(View.INVISIBLE);
}
if (mp.isPlaying()) {
// Log.e(Tag, "mp.isPlaying()");
}
}
好了,到这里,viewpager+videoview的开发就完成 了,其中用到的自定义的videoview类在上一篇讲到过,在这里再发一下,WrapVideoView.java:
public class WrapVideoView extends VideoView {
public WrapVideoView(Context context) {
super(context);
requestFocus();
}
public WrapVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrapVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(getWidth(), widthMeasureSpec);
int height = getDefaultSize(getHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onDetachedFromWindow() {
// TODO Auto-generated method stub
super.onDetachedFromWindow();
}
}
主界面MainActivity.java:
/**
* MainActivity 2016-10-18
*/
public class MainActivity extends Activity implements OnPageChangeListener,
OnPreparedListener, OnErrorListener, OnInfoListener,
OnCompletionListener {
private static final String Tag = "====MainActivity====";
ViewPager mViewPager;
MyPagerAdapter mAdapter;
/*** 本地视频路径 ***/
String path = Environment.getExternalStorageDirectory().getPath()
+ "/Test.mp4";
// /*** 网络视频路径 ***/
// String path =
// "http://";
/*** 视频路径集合 ***/
String[] paths = new String[] { path, path, path, path };
/*** viewpager的根视图数据集合 ***/
List mViewList;
/*** 当前页面索引 ***/
int currentItem = 0;
/*** 上一个页面索引 ***/
int lastItem = 0;
/*** 页面的视频控件集合 ***/
static List mVideoViewList;
/*** 页面播放进度控制器集合 ***/
static List mMediaControllerList;
/*** 页面视频缓冲图集合 ***/
static List mCacheViewList;
/*** 记录每个page页面视频播放的进度 ***/
static Map mCurrentPositions;
/*** 记录每个page页面的视频播放状态 ***/
static Map mIsPlaying;
// static Map mIsPageFirstAvaliable;// 记录每个page页面是否第一次加载
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) this.findViewById(R.id.mViewPager);
initializeData();
Log.e(Tag, "onCreate-------->");
}
private void initializeData() {
mViewList = new ArrayList();
mVideoViewList = new ArrayList();
mMediaControllerList = new ArrayList();
mCacheViewList = new ArrayList();
mCurrentPositions = new HashMap();
mIsPlaying = new HashMap();
// mIsPageFirstAvaliable = new HashMap();
for (int i = 0; i < paths.length; i++) {
ViewGroup v = (ViewGroup) View.inflate(this, R.layout.page_layout,
null);
VideoView vv = (VideoView) v.findViewById(R.id.mVideoView);
View mView = (View) v.findViewById(R.id.mView);
MediaController mpc = new MediaController(this);
vv.setVideoPath(paths[i]);// 本地视频
// vv.setVideoURI(Uri.parse(path));// 网络视频
vv.setMediaController(mpc);
setListener(vv);
mViewList.add(v);
mVideoViewList.add(vv);
mMediaControllerList.add(mpc);
mCacheViewList.add(mView);
mCurrentPositions.put(i, 0);// 每个页面的初始播放进度为0
mIsPlaying.put(i, true);// 每个页面的初始播放状态false
// mIsPageFirstAvaliable.put(i, true);// 每个页面默认第一次
}
mAdapter = new MyPagerAdapter(this, mViewList);
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(this);
if (mVideoViewList.get(0) != null) {
mVideoViewList.get(0).start();
mIsPlaying.put(0, true);
// mIsPageFirstAvaliable.put(0, false);
}
}
private void setListener(VideoView vv) {
vv.setOnInfoListener(this);
vv.setOnCompletionListener(this);
vv.setOnErrorListener(this);
vv.setOnPreparedListener(this);
}
class MyPagerAdapter extends android.support.v4.view.PagerAdapter {
Context context;
List mViewList;
public MyPagerAdapter(Context context, List list) {
this.context = context;
this.mViewList = list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mViewList != null ? mViewList.size() : 0;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == (View) arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
// super.destroyItem(container, position, object);
container.removeView(mViewList.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(mViewList.get(position));
return mViewList.get(position);
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int pageIndex) {
lastItem = currentItem;
currentItem = pageIndex;
// Log.e(Tag, "currentItem: " + currentItem);
if (mVideoViewList.get(lastItem) != null) {
if (mVideoViewList.get(lastItem).isPlaying()) {
mIsPlaying.put(lastItem, true);// 记录播放状态
mVideoViewList.get(lastItem).pause();
} else {
mIsPlaying.put(lastItem, false);// 记录播放状态
}
mCurrentPositions.put(lastItem, mVideoViewList.get(lastItem)
.getCurrentPosition());// 记录播放进度
}
if (mMediaControllerList.get(lastItem) != null) {
if (mMediaControllerList.get(lastItem).isShowing()) {
mMediaControllerList.get(lastItem)
.setVisibility(View.INVISIBLE);
}
}
if (mVideoViewList.get(currentItem) != null) {
// 如果页面第一次加载
// if (mIsPageFirstAvaliable.get(currentItem)) {
// mIsPlaying.put(currentItem, true);
// mIsPageFirstAvaliable.put(currentItem, false);
// } else {
// 不是第一次加载跳到当前播放进度
mVideoViewList.get(currentItem).seekTo(
mCurrentPositions.get(currentItem));
// }
if (mIsPlaying.get(currentItem)) {
mVideoViewList.get(currentItem).start();
}
mMediaControllerList.get(currentItem).show(1000);
}
}
@Override
public void onCompletion(MediaPlayer mp) {
if (mVideoViewList.get(currentItem) != null) {
mCurrentPositions.put(currentItem, 0);// 重新播放,进度重置为0
mIsPlaying.put(currentItem, true);// 播放状态:正在播放
mVideoViewList.get(currentItem).resume();
mVideoViewList.get(currentItem).start();
}
}
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(View.VISIBLE);
}
} else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
// 此接口每次回调完START就回调END,若不加上判断就会出现缓冲图标一闪一闪的卡顿现象
if (mp.isPlaying()) {
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(
View.INVISIBLE);
}
}
}
return true;
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
// 这里设置为true防止弹出对话框,屏蔽原始出错的处理
return true;
}
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
if (mCacheViewList.get(currentItem) != null) {
mCacheViewList.get(currentItem).setVisibility(View.INVISIBLE);
}
if (mp.isPlaying()) {
// Log.e(Tag, "mp.isPlaying()");
}
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if (mVideoViewList.get(currentItem) != null) {
if (mVideoViewList.get(currentItem).isPlaying()) {
mIsPlaying.put(currentItem, true);
mVideoViewList.get(currentItem).pause();
} else {
mIsPlaying.put(currentItem, false);
}
mCurrentPositions.put(currentItem, mVideoViewList.get(currentItem)
.getCurrentPosition());
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (mVideoViewList.get(currentItem) != null) {
mVideoViewList.get(currentItem).stopPlayback();
mVideoViewList.get(currentItem).suspend();
}
clearList();
Log.e(Tag, "onDestroy-------->");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
if (mVideoViewList.get(currentItem) != null) {
mVideoViewList.get(currentItem).seekTo(
mCurrentPositions.get(currentItem));
if (mIsPlaying.get(currentItem)) {
mVideoViewList.get(currentItem).start();
}
}
}
/**
* 清空static数据
*/
private void clearList() {
mVideoViewList.clear();
mMediaControllerList.clear();
mCacheViewList.clear();
mCurrentPositions.clear();
mIsPlaying.clear();
}
}
源码下载地址