多媒体播放

来源:互联网 发布:怎么切换网络节点 编辑:程序博客网 时间:2024/04/30 18:06

一、VideoView播放视频


1.1 简介:

VideoView,用于播放一段视频媒体,它继承了SurfaceView,位于"android.widget.VideoView",是一个视频控件。


1.2 使用

  • 权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  • 布局:

<?xml version="1.0"encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#88000000"

    >


    <VideoView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/vvtest"

        android:layout_centerInParent="true"

        />


</RelativeLayout>

  • 播放手机中的本地视频:

private final String strVideoPath = "/sdcard/Download/splash.mp4";

vvTest.setVideoPath(strVideoPath);

vvTest.start();

  • 播放网络视频:

加入网络权限

<uses-permission android:name="android.permission.INTERNET"/>


设定网络视频地址并播放:

private final String strVideoUrl = "http://qv1.fit-time.cn/rockfit-vicky-plt-medium-6.mp4";

vvTest.setVideoPath(strVideoPath);

vvTest.start();


  • 播放视频资源(res/raw下面的视频):

String struri = "android.resource://"+ getPackageName() +"/" + R.raw.splash;

Uri uri = Uri.parse(struri);

vvTest.setVideoURI(uri);//vvTest.setVideoPath(struri);也可以

vvTest.start();

  • 获取视频总时长--getDuration

vvTest.setOnPreparedListener(newMediaPlayer.OnPreparedListener() {

    @Override

    public void onPrepared(MediaPlayer mp) {

        int iDuration =vvTest.getDuration();

        Log.d("qf","视频总时长:"+iDuration);

    }

});

要在视频装载完成的监听事件中,才能获得视频的准确时长,否则的话,比如在start之前或之后获取时长可能是-1


  • 跳到视频设定的位置(seekTo):

mac下模拟器中很多视频不能播放,能播放的拖动可能也有问题(用系统播放器播放也有同样的问题),所以此处使用真机测试

如果seekto方法不能正确执行,可以看下视频源在自带播放器中是否可以正常拖拉


seekto是异步执行的,不需要在视频装载完成后调用,在setVideoPath后调用就可以了(start前后调用都可以)


String struri = "android.resource://"+ getPackageName() +"/" + R.raw.db;

vvTest.setVideoPath(struri);

vvTest.seekTo(60*1000);

vvTest.start();


  • 获取当前播放到的时长(getCurrentPosition

String struri = "android.resource://"+ getPackageName() +"/" + R.raw.db;

vvTest.setVideoPath(struri);

vvTest.start();


new Handler().postDelayed(newRunnable() {

    @Override

    public void run() {

        int iCurPos =vvTest.getCurrentPosition();

        Log.e("qf","当前播放时长:"+iCurPos);

    }

}, 6000);

6s后获取当前播放的时长(单位ms),打印出来可能是5点几秒,因为start后不一定马上播放,要准备一点时间,帧的时隙也会有影响



  • 判断当前是否播放状态:isPlaying
  • 暂停:pause
  • 停止:stopPlayback

Handler handler = new Handler();

handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        if (vvTest.isPlaying()){

            vvTest.pause();

        }

    }

}, 6000);


handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        if (!vvTest.isPlaying()){

            vvTest.start();

        }


    }

}, 10000);


handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        vvTest.stopPlayback();

    }

}, 15000);

播放视频中间按home键,再调出视频播放界面时接着播放:


@Override

protected void onPause() {

    super.onPause();

    iStopPos =vvTest.getCurrentPosition();//保存切换时的进度

    vvTest.pause();

}


@Override

protected void onStop() {


    super.onStop();

}


@Override

protected void onStart() {

    super.onStart();

    vvTest.seekTo(iStopPos);//调到保存的进度中

    vvTest.start();


}

不能在onStop中写onPause的那两句代码,onStop时,videoview当前进度已经被重置为0了


  • 播放完毕的监听:setOnCompletionListener

vvTest.setOnCompletionListener(newMediaPlayer.OnCompletionListener() {

    @Override

    public void onCompletion(MediaPlayer mp) {

        Log.e("qf","播放结束");

    }

});

如果调用stopPlayback结束,不会调用这个监听方法,也不会调用error监听



  • 播放错误时的监听:setOnErrorListener

vvTest.setOnErrorListener(newMediaPlayer.OnErrorListener() {

    @Override

    public boolean onError(MediaPlayer mp, intwhat, intextra) {

        Log.e("qf","发生错误");

        return false;

    }

});

发生错误,比如播放一个不能播放的视频时,调用此监听


  • 全屏播放:

第一种方法,在布局中定义:


<?xml version="1.0"encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="#88000000"

    >


    <VideoView

        android:layout_alignParentTop="true"

        android:layout_alignParentBottom="true"

        android:layout_alignParentLeft="true"

        android:layout_alignParentRight="true"


        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/vvtest"

        android:layout_centerInParent="true"

        />


</RelativeLayout>

第二种方法,代码里实现对布局的控制:

RelativeLayout.LayoutParams layoutParams=

        new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,

                RelativeLayout.LayoutParams.MATCH_PARENT);

layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);

layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);

layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

vvTest.setLayoutParams(layoutParams);

第三种方法,重写onMeasure方法:

public class MyVideoViewextendsVideoView {


    private int mVideoWidth;

    private int mVideoHeight;

    public MyVideoView(Context context) {

        super(context);

    }


    public MyVideoView(Context context,AttributeSet attrs) {

        this(context,attrs,0);

    }


    public MyVideoView(Context context,AttributeSet attrs, intdefStyle) {

        super(context,attrs,defStyle);

    }


    public void setDimensions(intw, inth) {

        this.mVideoWidth= h;

        this.mVideoHeight= w;


    }


    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

      

        int width = getDefaultSize(mVideoWidth,widthMeasureSpec);

        int height = getDefaultSize(mVideoHeight,heightMeasureSpec);

        setMeasuredDimension(width,height);



    }

}


getDefaultSize:得到设置的宽或高,第一个参数是默认size,第二个参数是父控件约束的值,只有第二个参数不约束的时候,才会采用第一个值


setMeasuredDimension:真正把宽高应用到控件的方法,父控件的onMeasure最终也是调用这个方法


使用这个自定义的VideoView后,宽高就可以由布局文件的设置决定了,比如设置为match_parent就可以使视频全屏播放了



<?xml version="1.0"encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


    <com.example.zhouyi.videoviewtest.MyVideoView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/myvv"/>


</LinearLayout>


可以看下VideView的源码中onMeasure方法,里面通过计算,对videoview的宽高做了约束,使之匹配所播放视频的真实宽高比


  • 横竖屏切换

点击按钮横竖屏切换:

public void onChange(View view) {

    int iOrientation = getRequestedOrientation()

    if (iOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);


    } else{

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    }

}

如果之前没有调用setRequestedOrientation或在xml设置activity的方向,getRequestedOrientation会返回-1,所以先在xml中配置好方向或在oncreate中setRequestedOrientation为固定方向


默认情况下,横竖屏切换会销毁原来的activity,重新建立一个activity,这样视频就会重头开始播放,如果要在切换视频时,不重头播放,需要在清单文件的activity中加入如下配置(android3.2以后):

android:configChanges="keyboardHidden|orientation|screenSize"

Andorid 3.2以前的SDK可以使用如下配置

android:configChanges="orientation|keyboardHidden”

configChanges配置表示在发生配置所指定的变化时会通知系统调用onConfigurationChanged方法(比如orientation表示发生屏幕方向变化时调用onConfigurationChanged方法)

配置了这个属性,不会销毁原来的activity再重新创建,这样就不会走一遍生命周期,只会调用onConfigurationChanged方法

在onConfigurationChanged方法中重新设置videoview大小:

@Override

    public void onConfigurationChanged(Configuration newConfig) {

        super.onConfigurationChanged(newConfig);



        if (newConfig.orientation== Configuration.ORIENTATION_LANDSCAPE) {


            vvTest.setDimensions(displayHeight,displayWidth);

            vvTest.getHolder().setFixedSize(displayHeight,displayWidth);//使videoview重绘,触发onmeasure


        } else if(newConfig.orientation== Configuration.ORIENTATION_PORTRAIT){


            vvTest.setDimensions(displayWidth,displayHeight);

            vvTest.getHolder().setFixedSize(displayWidth,displayHeight);


        }

    }


setFixedSize让设定的宽高起作用,固定为设置的宽高,否则重写的onmeasrue方法里面不会采用设定的size值,而是用系统测量的widthMeasureSpec/heightMeasureSpec


获取屏幕宽高:

WindowManager wm = this.getWindowManager();

displayWidth = wm.getDefaultDisplay().getWidth();

displayHeight = wm.getDefaultDisplay().getHeight();

  • 使用MediaController做播放控制:

vvmc = (VideoView) findViewById(R.id.vvmc);

vvmc.setVideoPath(strVideoPath);


MediaController controller = newMediaController(this);

vvmc.setMediaController(controller);

二、MediaPlayer播放音视频:

2.1 简介:

VideoView其实是对MediaPlayer的封装,里面很多方法都是调用MediaPlayer对象实现的,MediaPlayer才是真正播放和控制音视频的类,VideoView使用起来更简单,但是MediaPlayer的定制性更好(品牌机和组装机的区别)


2.2 播放音频

  • 播放本地音频

private MediaPlayer mp = new MediaPlayer();

String strSound = "/sdcard/Download/yy.mp3";


try {

    mp.setDataSource(strSound);

    mp.prepare();

    mp.start();

} catch (IOException e) {

    e.printStackTrace();

}



Handler handler =  new Handler();

handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        mp.pause();

    }

}, 5000);


handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        mp.start();

    }

}, 10000);


handler.postDelayed(new Runnable() {

    @Override

    public void run() {

        mp.stop();

    }

}, 15000);

prepare用于播放前的准备,必须调用,是同步执行的

  • 播放网络音频:

把地址变成网络地址,加上网络权限即可:

String strSound = "http://ok.96x.cn/2015/6yue_2651.cn/%E6%BC%94%E5%91%98%20-%20%E8%96%9B%E4%B9%8B%E8%B0%A6.mp3";

prepare是同步执行的,所以最好放到子线程中,准备完毕后通知主线程播放,否则会阻塞主线程

也可以调用异步prepare,prepareAsync():

String strSound = "http://ok.96x.cn/2015/6yue_2651.cn/%E6%BC%94%E5%91%98%20-%20%E8%96%9B%E4%B9%8B%E8%B0%A6.mp3";


try {

    mp.setDataSource(strSound);

    mp.prepareAsync();

    mp.setOnPreparedListener(newMediaPlayer.OnPreparedListener() {

        @Override

        public void onPrepared(MediaPlayer mp) {

            mp.start();

        }

    });


} catch (IOException e) {

    e.printStackTrace();

}


  • 播放资源里的音频

mp = MediaPlayer.create(this,R.raw.yy);

mp.start();

create里面调用了prepare,不需要在外面调用了


  • 释放资源

@Override

protected void onDestroy() {

    super.onDestroy();

    mp.release();

}

在程序销毁或之前,一定要调用


  • 其他功能方法参照VideoView
  • 2.3 播放视频:

  • SurfaceView

surfaceView和View最本质的区别在于:

surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。


SurfaceHolder.Callback会在SurfaceView创建,改变,销毁等事件发生时回调


  • MediaPlayer+SurfaceView播放视频

MedeaPlayer本身没有画面输出机制,必须关联一个surfaceview,在surfaceview里面进行画面绘制

布局:

<?xml version="1.0"encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">


    <SurfaceView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/sftest"/>


</LinearLayout>


不会保持宽高比,完全由布局的宽高决定视频大小

代码:

final String strVideoPath ="/sdcard/Download/splash.mp4";

SurfaceView sftest = (SurfaceView) findViewById(R.id.sftest);


mp = newMediaPlayer();


sftest.getHolder().addCallback(newSurfaceHolder.Callback() {

    @Override

    public void surfaceCreated(SurfaceHolder holder) {

        try {

            mp.setDisplay(holder);

            mp.setDataSource(strVideoPath);

            mp.prepare();

            mp.start();

        } catch(IOException e) {

            e.printStackTrace();

        }


    }


    @Override

    public void surfaceChanged(SurfaceHolder holder, intformat, intwidth, intheight) {


    }


    @Override

    public void surfaceDestroyed(SurfaceHolder holder) {


    }

});

通过setdisplay方法把mediaplayer关联到一个surfaceview,视频是在surfaceview上绘制的

  • MediaPlayer生命周期:





通过setLooping方法可以控制视频是否循环播放

通过reset方法可以重置视频,比如播放多个视频,第一个视频还没有播放完毕,用户触发播放第二个视频,就要先调用reset方法


里面的其他方法参考VideoPlayer部分,VideoPlayer其实是调用MediaPlayer相关生命周期方法

Idle 状态:当使用new()方法创建一个MediaPlayer对象或者调用了其reset()方法时,该MediaPlayer对象处于idle状态。

End 状态:通过release()方法可以进入End状态,只要MediaPlayer对象不再被使用,就应当尽快将其通过release()方法释放掉,以释放相关的软硬件组件资源。如果MediaPlayer对象进入了End状态,则不会在进入任何其他状态了

Initialized 状态:这个状态比较简单,MediaPlayer调用setDataSource()方法就进入Initialized状态,表示此时要播放的文件已经设置好了。

Prepared 状态:初始化完成之后还需要通过调用prepare()prepareAsync()方法,这两个方法一个是同步的一个是异步的,只有进入Prepared状态,才表明MediaPlayer到目前为止都没有错误,可以进行文件播放。

Started 状态:显然,MediaPlayer一旦准备好,就可以调用start()方法,这样MediaPlayer就处于Started状态,这表明MediaPlayer正在播放文件过程中。可以使用isPlaying()测试MediaPlayer是否处于了Started状态。如果播放完毕,而又设置了循环播放,则MediaPlayer仍然会处于Started状态,类似的,如果在该状态下MediaPlayer调用了seekTo()或者start()方法均可以让MediaPlayer停留在Started状态。

Paused 状态:Started状态下MediaPlayer调用pause()方法可以暂停MediaPlayer,从而进入Paused状态,MediaPlayer暂停后再次调用start()则可以继续MediaPlayer的播放,转到Started状态,暂停状态时可以调用seekTo()方法,这是不会改变状态的。

Stop 状态:Started或者Paused状态下均可调用stop()停止MediaPlayer,而处于Stop状态的MediaPlayer要想重新播放,需要通过prepareAsync()prepare()回到先前的Prepared状态重新开始才可以。

PlaybackCompleted状态:文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListeneronCompletion()方法。此时可以调用start()方法重新从头播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()来重新定位播放位置。

Error状态:如果由于某种原因MediaPlayer出现了错误,会触发OnErrorListener.onError()事件,此时MediaPlayer即进入Error状态,及时捕捉并妥善处理这些错误是很重要的,可以帮助我们及时释放相关的软硬件资源,也可以改善用户体验。通过setOnErrorListener(android.media.MediaPlayer.OnErrorListener)可以设置该监听器。如果MediaPlayer进入了Error状态,可以通过调用reset()来恢复,使得MediaPlayer重新返回到Idle状态。


三、listview中播放视频(一般只同时播放一条,滑出屏幕外的暂停播放):

item布局:


<?xml version="1.0"encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="300dp">

    <VideoView

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_centerInParent="true"

        android:id="@+id/vv_item"/>


    <ImageView

        android:id="@+id/video_image"

        android:layout_width="fill_parent"

        android:layout_height="300dp"

        android:scaleType="fitXY"

        android:background="@drawable/video2"

        />


    <ImageButton

        android:id="@+id/video_play_btn"

        android:layout_width="45dp"

        android:layout_height="45dp"

        android:layout_centerInParent="true"

        android:background="@drawable/ic_play_video"

        />

</RelativeLayout>


adapter:

package com.example.zhouyi.listitemvideo;


import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageButton;

import android.widget.ImageView;

import android.widget.VideoView;


import java.util.List;


public class MyAdapter extends BaseAdapter {


    List<String> mListVideos;

    Context mContext;

   



    public MyAdapter(List<String> lstVides,Context context){

        mListVideos = lstVides;

        mContext = context;

    }


    @Override

    public int getCount() {

        return mListVideos.size();

    }


    @Override

    public ObjectgetItem(intposition) {

        return mListVideos.get(position);

    }


    @Override

    public long getItemId(intposition) {

        return position;

    }


    @Override

    public ViewgetView(final intposition,View convertView,ViewGroup parent) {

        final MyHolder holder;

        if (convertView ==null){

            convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_item,parent,false);

            VideoView vvtest = (VideoView) convertView.findViewById(R.id.vv_item);

            ImageButton ivbtest = (ImageButton) convertView.findViewById(R.id.video_play_btn);

            ImageView ivtest = (ImageView) convertView.findViewById(R.id.video_image);


            holder = new MyHolder();

            holder.vvtest= vvtest;

            holder.ivbtest= ivbtest;

            holder.ivtest= ivtest;


            convertView.setTag(holder);

        }else{

            holder = (MyHolder) convertView.getTag();

        }




        holder.ivbtest.setOnClickListener(newView.OnClickListener() {

            @Override

            public void onClick(View v) {

                holder.ivtest.setVisibility(View.GONE);

                holder.ivbtest.setVisibility(View.GONE);

               

                holder.vvtest.setVideoPath(mListVideos.get(position));

                holder.vvtest.start();


            }

        });


        return convertView;

    }


    class MyHolder{

        public VideoViewvvtest;

        public ImageViewivtest;

        public ImageButtonivbtest;

    }


}

初始化控件,解决复用时错位问题:

adapter中用一个成员变量mCurrentPos保存正在播放的item的position:

int mCurrentPos = -1;

如果不是正在播放的item,隐藏videoview

如果是正在播放的item,显示videoview,隐藏按钮和图片,开始播放




    @Override

    public ViewgetView(final intposition,View convertView,ViewGroup parent) {

        final MyHolder holder;

        if (convertView ==null){

            convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_item,parent,false);

            VideoView vvtest = (VideoView) convertView.findViewById(R.id.vv_item);

            ImageButton ivbtest = (ImageButton) convertView.findViewById(R.id.video_play_btn);

            ImageView ivtest = (ImageView) convertView.findViewById(R.id.video_image);


            holder = new MyHolder();

            holder.vvtest= vvtest;

            holder.ivbtest= ivbtest;

            holder.ivtest= ivtest;


            convertView.setTag(holder);

        }else{

            holder = (MyHolder) convertView.getTag();

        }



        if (position != mCurrentPos){

            holder.ivbtest.setVisibility(View.VISIBLE);

            holder.ivtest.setVisibility(View.VISIBLE);

        }else {

            holder.ivbtest.setVisibility(View.GONE);

            holder.ivtest.setVisibility(View.GONE);

            

        }



        holder.ivbtest.setOnClickListener(newView.OnClickListener() {

            @Override

            public void onClick(View v) {

                holder.ivtest.setVisibility(View.GONE);

                holder.ivbtest.setVisibility(View.GONE);

                mCurrentPos = position;

                holder.vvtest.setVideoPath(mListVideos.get(position));

                holder.vvtest.start();


            }

        });


        return convertView;

    }



当前item开始播放时,停止前面正在播放的视频:

首先在adpter中定义一个成员变量,存放目前正在播放视频的item对应的viewholder

MyHolder playingHolder=null;

用户点击下一个将要播放的视频时,在点击事件中,先停止当前播放的视频,并把按钮和图片设置为可见

@Override

public View getView(final intposition,View convertView,ViewGroup parent) {

    final MyHolder holder;

    if (convertView == null){

        convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_item,parent,false);

        VideoView vvtest = (VideoView) convertView.findViewById(R.id.vv_item);

        ImageButton ivbtest = (ImageButton) convertView.findViewById(R.id.video_play_btn);

        ImageView ivtest = (ImageView) convertView.findViewById(R.id.video_image);


        holder = new MyHolder();

        holder.vvtest= vvtest;

        holder.ivbtest= ivbtest;

        holder.ivtest= ivtest;


        convertView.setTag(holder);

    }else{

        holder = (MyHolder) convertView.getTag();

    }



    if (position !=mCurrentPos){

        holder.ivbtest.setVisibility(View.VISIBLE);

        holder.ivtest.setVisibility(View.VISIBLE);


    }else{

        holder.ivbtest.setVisibility(View.GONE);

        holder.ivtest.setVisibility(View.GONE);


    }



    holder.ivbtest.setOnClickListener(newView.OnClickListener() {

        @Override

        public void onClick(View v) {


  if (playingHolder != null){


                if(playingHolder.vvtest.isPlaying()){

                    playingHolder.vvtest.stopPlayback();

                    playingHolder.ivbtest.setVisibility(View.VISIBLE);

                    playingHolder.ivtest.setVisibility(View.VISIBLE);


                }

            }


            holder.ivtest.setVisibility(View.GONE);

            holder.ivbtest.setVisibility(View.GONE);

            mCurrentPos = position;

            holder.vvtest.setVideoPath(mListVideos.get(position));


            

            

            holder.vvtest.start();


            playingHolder = holder;


        }

    });


    return convertView;

}



item滑出屏幕时暂停播放:


在activity中回调listview的滑动事件,判断当前播放视频的item是否滑出屏幕之外,如果滑出了,暂停播放

lvtest.setOnScrollListener(newAbsListView.OnScrollListener() {


    @Override

    public void onScrollStateChanged(AbsListView view, intscrollState) {

        // TODO Auto-generated method stub


    }


    @Override

    public void onScroll(AbsListView view, intfirstVisibleItem,

                         int visibleItemCount, inttotalItemCount) {


        if (adapter.mCurrentPos< firstVisibleItem

                || adapter.mCurrentPos>lvtest.getLastVisiblePosition()) {

            if ((adapter.playingHolder!=null)

                    && adapter.playingHolder.vvtest.isPlaying()) {

                adapter.playingHolder.vvtest.pause();

            }

        }


    }

});




滑出屏幕再滑入,则重新播放;播放完毕后,重置界面和状态标志


@Override

public View getView(final intposition,View convertView,ViewGroup parent) {

    final MyHolder holder;

    if (convertView == null){

        convertView = LayoutInflater.from(mContext).inflate(R.layout.layout_item,parent,false);

        VideoView vvtest = (VideoView) convertView.findViewById(R.id.vv_item);

        ImageButton ivbtest = (ImageButton) convertView.findViewById(R.id.video_play_btn);

        ImageView ivtest = (ImageView) convertView.findViewById(R.id.video_image);


        holder = new MyHolder();

        holder.vvtest= vvtest;

        holder.ivbtest= ivbtest;

        holder.ivtest= ivtest;


        convertView.setTag(holder);

    }else{

        holder = (MyHolder) convertView.getTag();

    }



    if (position !=mCurrentPos){

        holder.ivbtest.setVisibility(View.VISIBLE);

        holder.ivtest.setVisibility(View.VISIBLE);


    }else{

        holder.ivbtest.setVisibility(View.GONE);

        holder.ivtest.setVisibility(View.GONE);

        if (!holder.vvtest.isPlaying()){

            holder.vvtest.start();

        }


    }


    holder.vvtest.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

        @Override

        public void onCompletion(MediaPlayer mp) {

            playingHolder.ivbtest.setVisibility(View.VISIBLE);

            playingHolder.ivtest.setVisibility(View.VISIBLE);

            playingHolder = null;

            mCurrentPos = -1;

        }

    });



    holder.ivbtest.setOnClickListener(newView.OnClickListener() {

        @Override

        public void onClick(View v) {

            holder.ivtest.setVisibility(View.GONE);

            holder.ivbtest.setVisibility(View.GONE);

            mCurrentPos = position;

            holder.vvtest.setVideoPath(mListVideos.get(position));


            if (playingHolder!=null){


                if(playingHolder.vvtest.isPlaying()){

                    playingHolder.vvtest.stopPlayback();

                    playingHolder.ivbtest.setVisibility(View.VISIBLE);

                    playingHolder.ivtest.setVisibility(View.VISIBLE);


                }

            }


            playingHolder=holder;

            holder.vvtest.start();




        }

    });


    return convertView;

}

练习:

videoview和seekbar互动,seekbar能实时显示进度,能拖拉进度

















0 0
原创粉丝点击