91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解Android 視頻滾動列表(偷懶型)

發布時間:2020-08-28 01:13:06 來源:腳本之家 閱讀:110 作者:書柜里的松鼠 欄目:移動開發

公司的項目需要一個視頻的滾動列表。

搜了些文章比較常見的是根據列表項的可視百分比來判斷的。實現起來略復雜。

這里想了一個在要求不高的情況下,實現相對簡便的方法:根據列表滾動時可見的第一個列表項的位置來播放和暫停對應列表項內的視頻。

它的效果大致是這樣的:

詳解Android 視頻滾動列表(偷懶型) 

以下是它的實現。

首先當然是建立列表。

這部分就直接用ListView吧,列表的具體的實現就不貼了。大致就是長這樣的一個列表:

詳解Android 視頻滾動列表(偷懶型) 

接下來就是添加播放器。

這里需要注意的是,在ListView里不能使用我們常用的那種VideoView。基于SurfaceView的VideoView由于沒有同步緩沖區,它不能在ListView中正常顯示。(顯然SurfaceView+MediaPlayer的形式也不太適合了)我們需要基于TextureView的視頻播放器。

這里偷個懶,就直接用 PLDroidPlayer這個庫中的PLVideoTextureView了

在列表的Adapter中的添加播放器。

Adapter的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <RelativeLayout
      android:id="@+id/videoTable"
      android:gravity="center"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
      <ImageView
        android:src="@drawable/videoico"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
      <com.pili.pldroid.player.widget.PLVideoTextureView
        android:id="@+id/myVideoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />
    </RelativeLayout>
    <TextView
      android:text="視頻名稱"
      android:id="@+id/videoName_t"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
  </LinearLayout>
</LinearLayout>

Adapter部分代碼:

package net.codepig.playerlist.adapers;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.pili.pldroid.player.AVOptions;
import com.pili.pldroid.player.PLMediaPlayer;
import com.pili.pldroid.player.widget.PLVideoTextureView;

import net.codepig.playerlist.R;
import net.codepig.playerlist.beans.VideoInfo;
import net.codepig.playerlist.deviceInfo;

import java.util.List;

/**
 * 視頻單元頁面
 * Created by QZD on 2017/11/13.
 */

public class PlayerAdapter extends BaseAdapter{
  private Context _context;
  private Activity mainActivity;
  private List<VideoInfo> myVideoData;
  private LayoutInflater inflater;
  private ViewHolder hodler = null;
  private PLMediaPlayer mPlayer=null;
//  private PLVideoTextureView myVideoView;
  private int _id;
  private String _name;
  private String _url="";

  private final String TAG="LOGCAT";

  public PlayerAdapter(Context context, List<VideoInfo> data) {
    super();
    _context = context;
    mainActivity=(Activity) context;
    myVideoData = data;
    inflater = LayoutInflater.from(context);
  }

  @Override
  public View getView(final int postion, View convertView, ViewGroup parent) {
    hodler = new ViewHolder();
    convertView = inflater.inflate(R.layout.player_adapter_l, null);
    hodler.videoName_t = convertView.findViewById(R.id.videoName_t);
    hodler.videoTable = convertView.findViewById(R.id.videoTable);
    hodler.myVideoView = convertView.findViewById(R.id.myVideoView);
    convertView.setTag(hodler);

    hodler.videoTable.getLayoutParams().width= deviceInfo._screenWidth;
    hodler.videoTable.getLayoutParams().height=deviceInfo._screenHeight;
//    Log.d(TAG,"screenSize:"+deviceInfo._screenWidth+"-"+deviceInfo._screenHeight);

    VideoInfo _vInfo=myVideoData.get(postion);
    _name=_vInfo.get_name();
    hodler.videoName_t.setText(_vInfo.get_name());
    _id=_vInfo.get_id();
    _url=_vInfo.get_url();
    if(!_url.equals("")) {
      setVideo(_url);
    }

    return convertView;
  }

  /**
   * 初始化播放器
   * @param url
   */
  private void setVideo(String url){
    int codec = mainActivity.getIntent().getIntExtra("mediaCodec", AVOptions.MEDIA_CODEC_AUTO);
    AVOptions options = new AVOptions();
    options.setInteger(AVOptions.KEY_PREPARE_TIMEOUT, 10 * 1000);
    options.setInteger(AVOptions.KEY_MEDIACODEC, codec);
    hodler.myVideoView.setAVOptions(options);
    hodler.myVideoView.setVideoPath(url);
    hodler.myVideoView.start();

    hodler.myVideoView.setOnErrorListener(new PLMediaPlayer.OnErrorListener(){
      @Override
      public boolean onError(PLMediaPlayer mp, int errorCode) {
        Log.d(TAG,"errorCode:"+errorCode);
        return true;
      }
    });
    hodler.myVideoView.setOnCompletionListener(new PLMediaPlayer.OnCompletionListener() {
      @Override
      public void onCompletion(PLMediaPlayer mp) {
//        Log.d(TAG, "player onCompletion:"+videoDuration/1000+"-"+_curTime/1000);
        hodler.myVideoView.seekTo(0);
        hodler.myVideoView.start();
      }
    });
    hodler.myVideoView.setOnPreparedListener(new PLMediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(PLMediaPlayer mediaPlayer, int percent) {
        Log.d(TAG, "player onPrepared");
        if(mPlayer==null){
          mPlayer=mediaPlayer;
        }
        //播放
        if(hodler.myVideoView!=null){
          hodler.myVideoView.start();
        }else{
          Log.d(TAG, _name+"no myVideoView");
        }
      }
    });
    hodler.myVideoView.setOnBufferingUpdateListener(new PLMediaPlayer.OnBufferingUpdateListener() {
      @Override
      public void onBufferingUpdate(PLMediaPlayer mp, int percent) {
        try {
          int _pec = hodler.myVideoView.getBufferPercentage();//百分比到99就停,進度條會留空
          if (_pec == 99) {
            _pec = 100;
          }
        }catch (Exception e){
          Log.d(TAG,"percentage error:"+e.toString());
        }
      }
    });
    hodler.myVideoView.setOnVideoSizeChangedListener(new PLMediaPlayer.OnVideoSizeChangedListener() {
      @Override
      public void onVideoSizeChanged(PLMediaPlayer plMediaPlayer, int width, int height) {
        Log.d(TAG,"VideoSize:"+width+"_"+height);
      }
    });
  }

  @Override
  public int getCount() {
    if (myVideoData != null) {
      return myVideoData.size();
    } else {
      return 0;
    }
  }

  @Override
  public Object getItem(int position) {
    return myVideoData.get(position);
  }

  @Override
  public long getItemId(int postion) {
    // TODO Auto-generated method stub
    return postion;
  }

  public static class ViewHolder {
    public TextView videoName_t;
    public RelativeLayout videoTable;
    public PLVideoTextureView myVideoView;
  }
}

添加完播放器大致長這樣:

詳解Android 視頻滾動列表(偷懶型) 

接下來就是重點了,要根據列表的滾動來播放和暫停視頻。

這里根據當前滾動的位置來進行判斷。

首先添加滾動監聽:

    myVideoList.setAdapter(playerAdapter);
    myVideoList.setOnScrollListener(new AbsListView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {
//        Log.d(TAG,"onScrollStateChanged:"+scrollState);
        //SCROLL_STATE_FLING = 滾動中;SCROLL_STATE_IDLE = 結束滾動;SCROLL_STATE_TOUCH_SCROLL = 開始滾動;
        if(scrollState==SCROLL_STATE_IDLE){
          Log.d(TAG,"FirstVisiblePosition:"+myVideoList.getFirstVisiblePosition());
          View v0=myVideoList.getChildAt(0);
          if(v0!=null){
            int scrollTop=v0.getTop();
            Log.d(TAG,"scroll top:"+scrollTop);
          }
        }
      }

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
      }
    });

這里通過getFirstVisiblePosition()獲得可見的第一個元素,并使用getTop()獲得該元素的偏移量。

接下來增加對元素內視頻的操作,這里通過更新列表的數據來實現。

修改一下上面的監聽,判斷當前第二個可見item的位置,當到達指定位置時將播放標識置為true。原先播放中的item的播放標識置為false。
然后更新數據。

     myVideoList.setOnScrollListener(new AbsListView.OnScrollListener() {
      @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {
        //SCROLL_STATE_FLING = 滾動中;SCROLL_STATE_IDLE = 結束滾動;SCROLL_STATE_TOUCH_SCROLL = 開始滾動;
        if(scrollState==SCROLL_STATE_IDLE){
          int _index=myVideoList.getFirstVisiblePosition()+1;
          View v1=myVideoList.getChildAt(1);//取可見元素的第二個
          if(v1!=null){
            int scrollTop=v1.getTop();
            if(scrollTop<200){
              if(_oldItem!=_index) {
                _infoList.get(_index).set_playing(true);
                _infoList.get(_oldItem).set_playing(false);
                _oldItem=_index;
                playerAdapter.notifyDataSetChanged();
              }
            }
//            Log.d(TAG,"scroll top:"+scrollTop);
          }
        }
      }

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
      }
    });

這個的位置判斷上直接寫死了200像素,作為一個DEMO,位置判斷的數值上不是很講究。這個其實應該根據滾動方向和item的高度來計算的。

在Adapter的getView()方法中根據_playing的狀態播放或停止視頻:(停止的時候要記得釋放掉播放器資源哦,不然列表中這么多視頻的內存占用是很可怕的哦。)

  @Override
  public View getView(final int postion, View convertView, ViewGroup parent) {
    hodler = new ViewHolder();
    convertView = inflater.inflate(R.layout.player_adapter_l, null);
    hodler.videoName_t = convertView.findViewById(R.id.videoName_t);
    hodler.videoTable = convertView.findViewById(R.id.videoTable);
    hodler.myVideoView = convertView.findViewById(R.id.myVideoView);
    convertView.setTag(hodler);

    hodler.videoTable.getLayoutParams().width= deviceInfo._screenWidth;
    hodler.videoTable.getLayoutParams().height=deviceInfo._screenHeight;
    Log.d(TAG,"screenSize:"+deviceInfo._screenWidth+"-"+deviceInfo._screenHeight);

    VideoInfo _vInfo=myVideoData.get(postion);
    _name=_vInfo.get_name();
    hodler.videoName_t.setText(_vInfo.get_name());
    _id=_vInfo.get_id();
    _url=_vInfo.get_url();
    if(!_url.equals("")) {
    //視頻的播放和停止
      if(_vInfo.get_playing()){
        setVideo(_url);
      }else{
        if(hodler.myVideoView!=null) {
          if (hodler.myVideoView.isPlaying()) {
            hodler.myVideoView.stopPlayback();
            hodler.myVideoView.releaseSurfactexture();
          }
        }
      }
    }
    return convertView;
  }

嗯,完工。

改天再整列表的可視百分比判斷。

相關github項目地址:https://github.com/codeqian/playerlist

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

文昌市| 陇川县| 洛扎县| 方城县| 南丰县| 专栏| 南雄市| 金山区| 遵义县| 阿荣旗| 淅川县| 南丹县| 浑源县| 虎林市| 泰兴市| 民县| 湛江市| 云安县| 叙永县| 永兴县| 竹山县| 湘潭市| 上栗县| 万全县| 黄陵县| 攀枝花市| 南安市| 于都县| 闻喜县| 新龙县| 张掖市| 铜陵市| 垫江县| 正安县| 陇川县| 西乌珠穆沁旗| 招远市| 银川市| 无锡市| 凤山县| 凤冈县|