Android视频播放之ViewPager+VideoView

由于项目需求,项目主页面有很多个page页面,每个page页面中都有一个VideoView用于播放视频,写次demo用来练手。

源码下载地址

1、上效果图:
Android视频播放之ViewPager+VideoView_第1张图片

由于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();
    }
}

源码下载地址

你可能感兴趣的:(android,viewpager)