开源播放器GSYVideoPlayer + ViewPager2 源码解析

开源播放器GSYVideoPlayer + ViewPager2 源码解析

  • 前言
  • 一、GSYVideoPlayer🔥🔥🔥是什么?
  • 二、源码解析
    • 1.ViewPager2Activity
  • 总结


在这里插入图片描述

前言

本文介绍GSYVideoPlayer源码中关于ViewPager2 +GSYVideoPlayer 实现的滑动播放列表的实现原理。

本文使用的版本为gsyVideoPlayerVersion = “7.1.4”


一、GSYVideoPlayer🔥🔥🔥是什么?

github地址: https://github.com/CarGuo/GSYVideoPlayer

让我们看看介绍:
视频播放器(IJKplayer、ExoPlayer、MediaPlayer),HTTPS支持,支持弹幕,支持滤镜、水印、gif截图,片头广告、中间广告,多个同时播放,支持基本的拖动,声音、亮度调节,支持边播边缓存,支持视频本身自带rotation的旋转(90,270之类),重力旋转与手动旋转的同步支持,支持列表播放 ,直接添加控件为封面,列表全屏动画,视频加载速度,列表小窗口支持拖动,动画效果,调整比例,多分辨率切换,支持切换播放器,进度条小窗口预览,其他一些小动画效果,rtsp、concat、mpeg。(总结,高端大气上档次)
让我们看看作者:
在这里插入图片描述
让我们看看文档:
在这里插入图片描述

优点

  • 支持好几种开源播放器,集大成者
  • 可以按需引用所需要的依赖,这样一来包体积不会太大
  • 作者维护很勤快,有什么问题issues,作者也会帮忙看看
  • 文档写的很清楚不需要额外查资料,实在不懂代码拉下来一跑,对照着代码基本上就能理解了

缺点:

-有一些版本对应会有不同的问题,比如我使用的时候用了最新的依赖,按照文档不能播放rtsp流,降低了依赖过后就可以播放了。

如果想使用其他播放器的可以看看我的这篇文章

安卓的播放器对比与选型(vlc,EXOplayer,Ijkplayer,GSYVideoPlayer)详细过程

二、源码解析

1.ViewPager2Activity

在ViewPager2Activity中,我们可以看到相关代码。

代码如下(示例):

 viewPagerAdapter = new ViewPagerAdapter(this, dataList);binding.viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);binding.viewPager2.setAdapter(viewPagerAdapter);binding.viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {super.onPageSelected(position);//大于0说明有播放int playPosition = GSYVideoManager.instance().getPlayPosition();if (playPosition >= 0) {//对应的播放列表TAGif (GSYVideoManager.instance().getPlayTag().equals(RecyclerItemNormalHolder.TAG)&& (position != playPosition)) {GSYVideoManager.releaseAllVideos();playPosition(position);}}}});binding.viewPager2.post(new Runnable() {@Overridepublic void run() {playPosition(0);}});}

这段代码是在使用Android中的ViewPager2来创建一个滑动页面效果。ViewPager2是Android提供的一个用于实现滑动页面效果的组件。下面是对这段代码的逐行解释:

  1. viewPagerAdapter = new ViewPagerAdapter(this, dataList); 这一行是创建一个ViewPager的适配器,其中this是指当前的Activity,dataList是用来提供数据给ViewPager的列表。
  2. binding.viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL); 这一行是设置ViewPager的滑动方向为垂直滑动。
  3. binding.viewPager2.setAdapter(viewPagerAdapter); 这一行是将刚刚创建的ViewPager适配器设置到ViewPager上。
  4. binding.viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {...}); 这一行是注册一个页面改变的回调。当ViewPager的页面发生改变时,会回调这个接口的实现。
  5. 在回调的实现中,int playPosition = GSYVideoManager.instance().getPlayPosition(); 获取当前播放的位置。
  6. if (playPosition >= 0) {...} 这个判断是为了确认当前有视频播放状态是正常的。
  7. 在这个if语句中,首先判断当前正在播放的视频的Tag是否等于RecyclerItemNormalHolder的Tag,如果不是,那么就释放所有的视频并跳转到当前的位置。这个逻辑是为了处理当页面发生改变时,如果当前播放的视频不在这个页面上,就停止播放并跳转到当前页面的视频。
  8. binding.viewPager2.post(new Runnable() {...}); 这一行代码在ViewPager的Looper中执行一个Runnable,这个Runnable会在ViewPager的UI线程中运行。
  9. 在Runnable的实现中,调用playPosition(0); 方法,是为了在页面加载完成后自动播放位于第一个位置的视频。

在上面的代码中,我们可以看到playPosition这个方法出现了两次,并且从名字中可以看出是播放的方法,我们接下来看看这个方法干了些什么。

    private void playPosition(int position) {binding.viewPager2.postDelayed(new Runnable() {@Overridepublic void run() {RecyclerView.ViewHolder viewHolder = ((RecyclerView) binding.viewPager2.getChildAt(0)).findViewHolderForAdapterPosition(position);if (viewHolder != null) {RecyclerItemNormalHolder recyclerItemNormalHolder = (RecyclerItemNormalHolder) viewHolder;recyclerItemNormalHolder.getPlayer().startPlayLogic();}}}, 50);}

可以看到playPosition通过findViewHolderForAdapterPosition方法找到了当前viewPager2对应的viewHolder,通过viewHolder的getPlayer()方法获取到了播放器,并开始了播放,我们再去看看RecyclerItemNormalHolder类。

package com.example.gsyvideoplayer.holder;import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;import com.example.gsyvideoplayer.R;
import com.example.gsyvideoplayer.databinding.ActivityDetailExoSubtitlePlayerBinding;
import com.example.gsyvideoplayer.model.VideoModel;
import com.example.gsyvideoplayer.video.SampleCoverVideo;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder;
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;import java.util.HashMap;
import java.util.Map;/*** Created by guoshuyu on 2017/1/9.*/public class RecyclerItemNormalHolder extends RecyclerItemBaseHolder {public final static String TAG = "RecyclerView2List";protected Context context;SampleCoverVideo gsyVideoPlayer;ImageView imageView;GSYVideoOptionBuilder gsyVideoOptionBuilder;public RecyclerItemNormalHolder(Context context, View v) {super(v);this.context = context;gsyVideoPlayer = v.findViewById(R.id.video_item_player);imageView = new ImageView(context);gsyVideoOptionBuilder = new GSYVideoOptionBuilder();}public void onBind(final int position, VideoModel videoModel) {String url;String title;if (position % 2 == 0) {url = "https://pointshow.oss-cn-hangzhou.aliyuncs.com/McTk51586843620689.mp4";title = "这是title";} else {url = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";title = "哦?Title?";}Map<String, String> header = new HashMap<>();header.put("ee", "33");//防止错位,离开释放//gsyVideoPlayer.initUIState();gsyVideoOptionBuilder.setIsTouchWiget(false)//.setThumbImageView(imageView).setUrl(url).setVideoTitle(title).setCacheWithPlay(false).setRotateViewAuto(true).setLockLand(true).setPlayTag(TAG).setMapHeadData(header).setShowFullAnimation(true).setNeedLockFull(true).setPlayPosition(position).setVideoAllCallBack(new GSYSampleCallBack() {@Overridepublic void onPrepared(String url, Object... objects) {super.onPrepared(url, objects);if (!gsyVideoPlayer.isIfCurrentIsFullscreen()) {//静音GSYVideoManager.instance().setNeedMute(true);}}@Overridepublic void onQuitFullscreen(String url, Object... objects) {super.onQuitFullscreen(url, objects);//全屏不静音GSYVideoManager.instance().setNeedMute(true);}@Overridepublic void onEnterFullscreen(String url, Object... objects) {super.onEnterFullscreen(url, objects);GSYVideoManager.instance().setNeedMute(false);gsyVideoPlayer.getCurrentPlayer().getTitleTextView().setText((String) objects[0]);}}).build(gsyVideoPlayer);//增加titlegsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);//设置返回键gsyVideoPlayer.getBackButton().setVisibility(View.GONE);//设置全屏按键功能gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {resolveFullBtn(gsyVideoPlayer);}});gsyVideoPlayer.loadCoverImageBy(R.mipmap.xxx2, R.mipmap.xxx2);}/*** 全屏幕按键处理*/private void resolveFullBtn(final StandardGSYVideoPlayer standardGSYVideoPlayer) {standardGSYVideoPlayer.startWindowFullscreen(context, true, true);}public SampleCoverVideo getPlayer() {return gsyVideoPlayer;}
}

为了让读者看的更清晰,我提了整个类,可以看到,在自身初始化时就对gsyVideoPlayer进行了初始化,并且在数据绑定的onBind方法中为了防止错位,专门设置了gsyVideoOptionBuilder,而getPlayer方法只是把gsyVideoPlayer返回。所以,实现列表播放的关键代码其实就是gsyVideoOptionBuilder

 gsyVideoOptionBuilder.setIsTouchWiget(false)//.setThumbImageView(imageView).setUrl(url).setVideoTitle(title).setCacheWithPlay(false).setRotateViewAuto(true).setLockLand(true).setPlayTag(TAG).setMapHeadData(header).setShowFullAnimation(true).setNeedLockFull(true).setPlayPosition(position)

总结

本文主要介绍了开源播放器GSYVideoPlayer和ViewPager2的结合使用,实现滑动播放列表的原理。通过对ViewPager2Activity、RecyclerItemNormalHolder等类中的代码解析,了解了如何在ViewPager2中播放视频,关键代码为gsyVideoOptionBuilder。GSYVideoPlayer支持多种开源播放器,具有较好的维护和文档,但使用时需注意不同版本对应问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/184565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMD-Attention-LSTM 价格预测实战

VMD-Attention-LSTM时间序列价格预测实战 完整数据代码可直接运行_哔哩哔哩_bilibili 数据展示:数据有几万条 足够的 主要模型代码: import tensorflow as tfdef attention_3d_block(inputs,TIME_STEPS,SINGLE_ATTENTION_VECTOR):# inputs.shape = (batch_size, time_steps,…

C#队列(Queue)及泛型类(Queue<T>)

队列实现先进先出&#xff0c;有装箱拆箱行为&#xff0c;可存放任意类型&#xff0c;但无法获取指定位置元素&#xff0c;只能取出最先存储的元素。 一、基本队列操作 1、向队列添加元素&#xff08;Enqueue&#xff09; Queue queue new Queue(); queue.Enqueue(1); queue.…

升级openssh以及回滚,telnet远程链接

目录 安装telnet 编译安装openssl 解压并编译安装OpenSSH 修改配置允许root用户远程登录 测试没问题后开启防火墙关闭telnet 回滚办法&#xff08;如果没有备份的话&#xff09; 安装telnet 为了防止升级安装失败&#xff0c;无法使用ssh做远程连接&#xff0c;因此安装…

区间合并笔记

文章目录 什么是区间合并怎么做区间合并AcWing 803. 区间合并思路解析my - CODEdalao の CODE 什么是区间合并 区间合并是指给定多个区间&#xff0c;让你将重合的区间合并为一个区间 怎么做区间合并 区间合并类问题大多三个办法&#xff1a; 按左端点排序按右端点排序按左右…

企业微信ipad版,http协议接口发开,获取客户群列表

版本介绍&#xff1a; HTTP协议接口可以通过该接口实现企业微信的各种功能&#xff0c;使用HTTP协议可以避免使用hook形式的需要开启PC客户端的方式&#xff0c;同时可以实现三端同时在线&#xff0c;不影响PC和手机端的登录状态&#xff0c;调用简单&#xff0c;可以支持几千…

Apache Doris 整合 FLINK CDC 、Paimon 构建实时湖仓一体的联邦查询入门

1.概览 多源数据目录&#xff08;Multi-Catalog&#xff09;功能&#xff0c;旨在能够更方便对接外部数据目录&#xff0c;以增强Doris的数据湖分析和联邦数据查询能力。 在之前的 Doris 版本中&#xff0c;用户数据只有两个层级&#xff1a;Database 和 Table。当我们需要连…

一键删除方舟编译器缓存文件js、js.map插件ArkCompilerSupport

新手学习鸿蒙开发&#xff0c;发现DevEco Studio编译过种会生成js、js.map&#xff0c;在论坛上看了其它开发者也提了问题但无没解决&#xff0c;写了一个插件大家试下&#xff1a; https://plugins.jetbrains.com/plugin/23192-arkcompilersupport 源码&#xff1a;https://g…

js 如何实现转驼峰处理

目录 1&#xff0c;需求2&#xff0c;实现和原理3&#xff0c;原理1&#xff0c;正则2&#xff0c;替换函数 1&#xff0c;需求 在开发中&#xff0c;有时需要将中划线 -&#xff0c;下划线 _&#xff0c;冒号 : 这些连接符转为驼峰形式。 如果只有一个连接符&#xff0c;处理…

深度学习——Loss汇总

深度学习——Loss汇总 一、IOU Loss二、L1 Loss 一、IOU Loss 公式&#xff1a; 参考资料: 目标检测回归损失函数——IOU、GIOU、DIOU、CIOU、EIOU 二、L1 Loss 公式&#xff1a; 参考资料: PyTorch中的损失函数–L1Loss /L2Loss/SmoothL1Loss

Day72x.算法训练

739. 每日温度 class Solution {public int[] dailyTemperatures(int[] temperatures) {LinkedList<Integer> st new LinkedList<>();st.push(0);int[] res new int[temperatures.length];for (int i 1; i < temperatures.length; i) {while (!st.isEmpty()…

python机器学习——简单神经网络算法回归分析

利用python实现简单的神经网络算法回归分析 2023年亚太杯数学建模C题可以使用这个代码进行分析 import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from tensorflow.keras.mod…

智慧城市大脑,运维无忧!

运维管理软件在智慧城市中发挥着重要的作用&#xff0c;可以提升IT资源管理效率、保障城市运营安全稳定、实现数据可视化与智能分析、优化资源配置与决策支持、促进智慧城市可持续发展。 在智慧城市中&#xff0c;运维管理软件的应用场景非常广泛。以下是其中几个具体应用场景…

Linux 网络配置

Linux 网络配置 #学习目标 1&#xff0c;掌握Linux中网络配置相关的文件。 2&#xff0c;掌握Linux中网络配置的相关参数。 3&#xff0c;掌握常用的网络配置命令。 4&#xff0c;管理Linux的常用网络服务。Linux系统下配置网络有两种方式&#xff1a; 在安装Linux系统的过程…

高并发架构设计方法:面对高并发,怎么对症下药?

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 我们知道&#xff0c;“高并发”是现在系统架构设计的核心关键词。一个架构师如果设计、开发的系统不支持高并发&#xff0c;那简直不好意思跟同行讨论。但事实上&#xff0c;在架构设计领域&#xff0c;高并发的历史…

DAPP开发【01】知识简介

系列文章目录 系列文章在DAPP开发专栏 文章目录 系列文章目录前言一、公/私钥是什么&#xff1f;二、区块浏览器三、用户和区块链交互1.infura 四、opensea 前言 DAPP&#xff0c;全称为Decentralized Application&#xff0c;即去中心化应用程序。它是一种基于区块链技术构建…

【C++】程序题( STL标准模板库)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

【element-plus使用】el-select自定义样式、下拉框选项过长等问题解决

1、自定义样式 <template><el-select v-model"value" style"width: 150px"><el-option label"选项一" value"option1"></el-option><el-option label"选项二" value"option2"><…

115. 不同的子序列

给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数&#xff0c;结果需要对 109 7 取模。 示例 1&#xff1a; 输入&#xff1a;s "rabbbit", t "rabbit" 输出&#xff1a;3 解释&#xff1a; 如下所示, 有 3 种可以从 s 中…

UG\NX二次开发 设置对象上属性的锁定状态UF_ATTR_set_user_attribute_lock_with_title_and_type

文章作者:里海 来源网站:里海NX二次开发3000例专栏 简介 设置对象上属性的锁定状态UF_ATTR_set_user_attribute_lock_with_title_and_type,用于代替旧版函数UF_ATTR_set_locked,使用旧版函数UF_ATTR_set_locked锁定属性请参照这篇文章《UG\NX二次开发 设置对象上属性的锁定…

PyMuPDF---Python处理PDF的宝藏库详解

1、PyMuPDF简介 1.1 介绍 在介绍PyMuPDF之前&#xff0c;先来了解一下MuPDF&#xff0c;从命名形式中就可以看出&#xff0c;PyMuPDF是MuPDF的Python接口形式。 MuPDF MuPDF 是一个轻量级的 PDF、XPS和电子书查看器。MuPDF 由软件库、命令行工具和各种平台的查看器组成。 …