饺子播放器RecyclerView自动播放

项目地址:https://github.com/AndroidLMY/JzPlayer

效果图如下

添加相关依赖

    implementation 'com.google.android.material:material:1.0.0'implementation 'androidx.recyclerview:recyclerview:1.0.0'implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'implementation 'com.github.bumptech.glide:glide:4.8.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'

如果添加以上依赖报下面的错误

请在build中android节点下添加

    compileOptions {targetCompatibility 1.8sourceCompatibility 1.8}

清单文件添加网络权限

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

自定义播放器MyJzvdStd继承JzvdStd类

package com.androidlmy.jzplayer;import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;import cn.jzvd.JzvdStd;/*** 这里可以监听到视频播放的生命周期和播放状态* 所有关于视频的逻辑都应该写在这里* Created by Nathen on 2017/7/2.*/
public class MyJzvdStd extends JzvdStd {public MyJzvdStd(Context context) {super(context);}public MyJzvdStd(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic void init(Context context) {super.init(context);}@Overridepublic void onClick(View v) {super.onClick(v);int i = v.getId();if (i == cn.jzvd.R.id.fullscreen) {Log.i(TAG, "onClick: fullscreen button");} else if (i == R.id.start) {Log.i(TAG, "onClick: start button");}}@Overridepublic boolean onTouch(View v, MotionEvent event) {super.onTouch(v, event);int id = v.getId();if (id == cn.jzvd.R.id.surface_container) {switch (event.getAction()) {case MotionEvent.ACTION_UP:if (mChangePosition) {Log.i(TAG, "Touch screen seek position");}if (mChangeVolume) {Log.i(TAG, "Touch screen change volume");}break;}}return false;}@Overridepublic int getLayoutId() {return R.layout.jz_layout_std;}@Overridepublic void startVideo() {super.startVideo();Log.i(TAG, "startVideo");}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {super.onStopTrackingTouch(seekBar);Log.i(TAG, "Seek position ");}@Overridepublic void gotoScreenFullscreen() {super.gotoScreenFullscreen();Log.i(TAG, "goto Fullscreen");}@Overridepublic void gotoScreenNormal() {super.gotoScreenNormal();Log.i(TAG, "quit Fullscreen");}@Overridepublic void autoFullscreen(float x) {super.autoFullscreen(x);Log.i(TAG, "auto Fullscreen");}@Overridepublic void onClickUiToggle() {super.onClickUiToggle();Log.i(TAG, "click blank");}//onState 代表了播放器引擎的回调,播放视频各个过程的状态的回调@Overridepublic void onStateNormal() {super.onStateNormal();}@Overridepublic void onStatePreparing() {super.onStatePreparing();}@Overridepublic void onStatePlaying() {super.onStatePlaying();}@Overridepublic void onStatePause() {super.onStatePause();}@Overridepublic void onStateError() {super.onStateError();}@Overridepublic void onStateAutoComplete() {super.onStateAutoComplete();Log.i(TAG, "Auto complete");}//changeUiTo 真能能修改ui的方法@Overridepublic void changeUiToNormal() {super.changeUiToNormal();}@Overridepublic void changeUiToPreparing() {super.changeUiToPreparing();}@Overridepublic void changeUiToPlayingShow() {super.changeUiToPlayingShow();}@Overridepublic void changeUiToPlayingClear() {super.changeUiToPlayingClear();}@Overridepublic void changeUiToPauseShow() {super.changeUiToPauseShow();}@Overridepublic void changeUiToPauseClear() {super.changeUiToPauseClear();}@Overridepublic void changeUiToComplete() {super.changeUiToComplete();}@Overridepublic void changeUiToError() {super.changeUiToError();}@Overridepublic void onInfo(int what, int extra) {super.onInfo(what, extra);}@Overridepublic void onError(int what, int extra) {super.onError(what, extra);}}

编写PlayerAdapter

package com.androidlmy.jzplayer;import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;import androidx.recyclerview.widget.RecyclerView;import com.bumptech.glide.Glide;import cn.jzvd.JzvdStd;/*** @功能:* @Creat 2019/11/1 15:11* @User Lmy* @Compony zaituvideo*/
public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.ViewHolder> {private Context context;public PlayerAdapter(Context context) {this.context = context;}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {ViewHolder holder = new ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_recyclerview, parent,false));return holder;}@SuppressLint("LongLogTag")@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {holder.videoplayer.setUp("http://jzvd.nathen.cn/6ea7357bc3fa4658b29b7933ba575008/fbbba953374248eb913cb1408dc61d85-5287d2089db37e62345123a1be272f8b.mp4","", JzvdStd.SCREEN_NORMAL);holder.videoplayer.setVideoImageDisplayType(1);holder.videoplayer.thumbImageView.setScaleType(ImageView.ScaleType.FIT_XY);
//        holder.videoplayer.startVideo();//自动播放 在recyclerview有bugGlide.with(holder.videoplayer.getContext()).load("http://jzvd-pic.nathen.cn/jzvd-pic/00b026e7-b830-4994-bc87-38f4033806a6.jpg").into(holder.videoplayer.thumbImageView);}@Overridepublic int getItemCount() {return 10;}class ViewHolder extends RecyclerView.ViewHolder {private MyJzvdStd videoplayer;public ViewHolder(View itemView) {super(itemView);videoplayer = itemView.findViewById(R.id.videoplayer);}}
}

主页面布局和Recyclerview的Item布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="300dp"><com.androidlmy.jzplayer.MyJzvdStdandroid:id="@+id/videoplayer"android:layout_width="match_parent"android:layout_height="match_parent" /></RelativeLayout>

主界面MainActivity代码如下:

package com.androidlmy.jzplayer;import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import android.content.Context;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;import cn.jzvd.Jzvd;import static cn.jzvd.Jzvd.STATE_PAUSE;
import static cn.jzvd.Jzvd.STATE_PLAYING;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private PlayerAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recycler_view);adapter = new PlayerAdapter(this);recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.setAdapter(adapter);recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {@Overridepublic void onChildViewAttachedToWindow(View view) {}@Overridepublic void onChildViewDetachedFromWindow(View view) {Jzvd jzvd = view.findViewById(R.id.videoplayer);if (jzvd != null && Jzvd.CURRENT_JZVD != null &&jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())) {if (Jzvd.CURRENT_JZVD != null && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {Jzvd.releaseAllVideos();}}}});recyclerView.addOnScrollListener(new AutoPlayScrollListener(this));}/*** 监听recycleView滑动状态,* 自动播放可见区域内的第一个视频*/private static class AutoPlayScrollListener extends RecyclerView.OnScrollListener {private int firstVisibleItem = 0;private int lastVisibleItem = 0;private int visibleCount = 0;private Context context;public AutoPlayScrollListener(Context context) {this.context = context;}/*** 被处理的视频状态标签*/private enum VideoTagEnum {/*** 自动播放视频*/TAG_AUTO_PLAY_VIDEO,/*** 暂停视频*/TAG_PAUSE_VIDEO}@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);switch (newState) {case RecyclerView.SCROLL_STATE_IDLE://停止滚动autoPlayVideo(recyclerView, VideoTagEnum.TAG_AUTO_PLAY_VIDEO);default:
//                    autoPlayVideo(recyclerView, VideoTagEnum.TAG_PAUSE_VIDEO);//滑动时暂停视频 需要可以加上break;}}@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();if (layoutManager instanceof LinearLayoutManager) {LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;firstVisibleItem = linearManager.findFirstVisibleItemPosition();lastVisibleItem = linearManager.findLastVisibleItemPosition();visibleCount = lastVisibleItem - firstVisibleItem;}}/*** 循环遍历 可见区域的播放器* 然后通过 getLocalVisibleRect(rect)方法计算出哪个播放器完全显示出来* <p>* getLocalVisibleRect相关链接:http://www.cnblogs.com/ai-developers/p/4413585.html** @param recyclerView* @param handleVideoTag 视频需要进行状态*/private void autoPlayVideo(RecyclerView recyclerView, VideoTagEnum handleVideoTag) {for (int i = 0; i < visibleCount; i++) {if (recyclerView != null && recyclerView.getChildAt(i) != null && recyclerView.getChildAt(i).findViewById(R.id.videoplayer) != null) {MyJzvdStd homeGSYVideoPlayer = (MyJzvdStd) recyclerView.getChildAt(i).findViewById(R.id.videoplayer);Rect rect = new Rect();homeGSYVideoPlayer.getLocalVisibleRect(rect);int videoheight = homeGSYVideoPlayer.getHeight();if (rect.top == 0 && rect.bottom == videoheight) {handleVideo(handleVideoTag, homeGSYVideoPlayer);// 跳出循环,只处理可见区域内的第一个播放器break;}}}}/*** 视频状态处理** @param handleVideoTag     视频需要进行状态* @param homeGSYVideoPlayer JZVideoPlayer播放器*/private void handleVideo(VideoTagEnum handleVideoTag, MyJzvdStd homeGSYVideoPlayer) {switch (handleVideoTag) {case TAG_AUTO_PLAY_VIDEO:if ((homeGSYVideoPlayer.state != STATE_PLAYING)) {// 进行播放homeGSYVideoPlayer.startVideo();}break;case TAG_PAUSE_VIDEO:if ((homeGSYVideoPlayer.state != STATE_PAUSE)) {// 模拟点击,暂停视频homeGSYVideoPlayer.startButton.performClick();}break;default:break;}}}/*** 拦截返回键 返回不退出程序*/@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (Jzvd.backPress()) {return true;} else {if (keyCode == KeyEvent.KEYCODE_BACK) {moveTaskToBack(true);return true;}}return super.onKeyDown(keyCode, event);}
}

横竖屏切换时需要在界面清单文件中添加:

android:configChanges="orientation|screenSize|keyboardHidden"属性

饺子播放器RecyclerView自动播放相关推荐

  1. YouTube iframe嵌入式播放器及播放器参数 自动播放,循环播放,播放列表,不显示 YouTube 徽标

    YouTube 嵌入式播放器及播放器参数 概览 本文档介绍如何在应用中嵌入 YouTube 播放器,并定义了 YouTube 嵌入式播放器可以使用的参数. 通过将参数附加到 iframe 网址末尾,您 ...

  2. python+tkinter+threading制作多线程简易音乐播放器(自动播放,上一曲,下一曲,播放,暂停,实时显示歌曲名并能自动切换歌曲的功能)

    https://blog.csdn.net/qq_41962782/article/details/80106158 小弟是小白因大作业,在此博文的基础上,我增加了歌曲目录的选择,自动播放,实时显示歌 ...

  3. android播放器实现自动播放,Android实现自动播放图片功能

    本文实例为大家分享了Android实现自动播放图片功能的具体代码,供大家参考,具体内容如下 第一种方式:回退到第一张 效果图 第二种方式:无限循环 效果图: 源代码 逻辑代码--MainActivit ...

  4. H5网页播放器EasyPlayer.js播放器界面的加载效果无法消失是什么原因?

    EasyPlayer支持视频播放画面秒开,画质高清.性能稳定,可支持的视频流格式有RTSP.RTMP.HLS.FLV.WebRTC等.我们也提供了简单易用的SDK及API接口,用户可以根据自己的需求, ...

  5. win10系统potplay播放器关闭自动更新方法

    描述:potplay播放器关闭自动更新方法 步骤: 左上角选择菜单,点击选项 基本->自动更新:选择不自动更新->应用确定

  6. android求助:关于播放器中的“播放/暂停”键: 用ImageButton来设置点击效果时的问题...

    ============问题描述============ 大家好,我最近遇到个问题:    大家都知道,播放器中的播放/暂停键是这样的逻辑:当用户点击了这个键,如果当前显示的是"播放&quo ...

  7. 关于音乐播放器锁屏播放,后台播放,封面显示等

    1. 如果应用需要后台播放:那么在appdelegate 中添加 [AVAudioSession *session = [AVAudioSession sharedInstance];[session ...

  8. Android音乐播放器开发(5)—播放界面(播放、暂停、上一首、下一首,顺序播放、随机播放、拖拽进度条…)

    1. 说明 源码已同步到Gitee仓库,Github仓库,觉得还不错的话帮忙点个"star"吧,非常感谢. Android播放器专栏其它文章: 服务端:Android音乐播放器开发 ...

  9. ios系统html播放音频播放器,iOS音频播放之AVAudioPlayer,AVPlayer,AVQueuePlayer

    本文以婚语APP为例,来讲解集体使用方法. 在婚语APP中,分别使用了AVAudioPlayer,AVPlayer,AVQueuePlayer来实现音频播放功能,下面以婚语的实际需求分别介绍它们的使用 ...

最新文章

  1. C1之路 | 训练任务01-进制与信息编码
  2. shell脚本一键安装nginx
  3. 浅谈EntityFramework框架的使用
  4. android-ViewPager不能显示
  5. IP路由故障关于BGP的疑问解答
  6. mysql数据库视图_MySQL数据库8(二十)视图
  7. java spring boot 项目 热加载 有利于快速开发
  8. 网易互娱面试总结(上)
  9. list集合去重和排序
  10. 计算机视觉知识体系图,计算机视觉系统框架的新构思
  11. 一、绘制不同类别特征均值标准差直方图
  12. 在网上请不要惹一个程序员
  13. python牛顿法算立方根_立方根求解(牛顿迭代法)
  14. 我的 iPhone XS Max 终于装上了这款高逼格数字时钟,优秀不优秀?!
  15. JAVA工程师个人简历中的项目经验范文
  16. Linux搭建eureka集群,基于dns搭建eureka集群
  17. 人脸识别活体检测之张张嘴和眨眨眼
  18. HDMI2.0/HDCP2.2 4x2 矩阵——GSV2008
  19. 2017年Q1中国无线路由器市场研究报告
  20. linux系统多网口聚合配置,linux端口聚合

热门文章

  1. Jmeter接口测试之响应断言
  2. Qt实战案例(42)——利用Qt实现自定义标题栏功能(自定义最大化、最小化、关闭等功能)
  3. .JSP和.HTML的区别
  4. CCF计算机软件能力认证试题练习:201512-2 消除类游戏
  5. 全志T507 核心板6路AHD摄像头解决方案_盈鹏飞嵌入式
  6. 如何添加npc以及相应的脚本
  7. linux 常用命令剪切cut
  8. python获取手机通知栏消息_Python编写的通知栏脚本启动工具
  9. 熔断器-Hystrix
  10. SSM Mybatis将新增数据写入数据库时出现的500状态码:Error updating database.的可能...