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

news2024/11/19 15:30:33

开源播放器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() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                //大于0说明有播放
                int playPosition = GSYVideoManager.instance().getPlayPosition();
                if (playPosition >= 0) {
                    //对应的播放列表TAG
                    if (GSYVideoManager.instance().getPlayTag().equals(RecyclerItemNormalHolder.TAG)
                        && (position != playPosition)) {
                        GSYVideoManager.releaseAllVideos();
                        playPosition(position);
                    }
                }
            }
        });
        binding.viewPager2.post(new Runnable() {
            @Override
            public 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() {
            @Override
            public 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() {
                @Override
                public void onPrepared(String url, Object... objects) {
                    super.onPrepared(url, objects);
                    if (!gsyVideoPlayer.isIfCurrentIsFullscreen()) {
                        //静音
                        GSYVideoManager.instance().setNeedMute(true);
                    }

                }

                @Override
                public void onQuitFullscreen(String url, Object... objects) {
                    super.onQuitFullscreen(url, objects);
                    //全屏不静音
                    GSYVideoManager.instance().setNeedMute(true);
                }

                @Override
                public void onEnterFullscreen(String url, Object... objects) {
                    super.onEnterFullscreen(url, objects);
                    GSYVideoManager.instance().setNeedMute(false);
                    gsyVideoPlayer.getCurrentPlayer().getTitleTextView().setText((String) objects[0]);
                }
            }).build(gsyVideoPlayer);


        //增加title
        gsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);

        //设置返回键
        gsyVideoPlayer.getBackButton().setVisibility(View.GONE);

        //设置全屏按键功能
        gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
            @Override
            public 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.coloradmin.cn/o/1269791.html

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

相关文章

(C++)复写零--双指针法

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

enote笔记法之附录1——“语法词”(即“关联词”)(ver0.24)

enote笔记法之附录1——“语法词”&#xff08;即“关联词”&#xff09;&#xff08;ver0.24&#xff09; 最上面的是截屏的完整版&#xff0c;分割线下面的是纯文字版本&#xff1a; 作者姓名&#xff08;本人的真实姓名&#xff09;&#xff1a;胡佳吉 居住地&#xff1…

A*算法学习

系列文章目录 前言 在总结 2023华为软件精英挑战赛——全赛段思路分享与总结 - 知乎 (zhihu.com)时&#xff0c;发现自己还有很多技术细节没搞懂&#xff0c;这里看静态全局路径规划最常见的A*算法&#xff0c;这个博主讲得很好&#xff1a; A-Star&#xff08;A*&#xff0…

AI模特换装的前端实现

本文作者为 360 奇舞团前端开发工程师 随着AI的火热发展&#xff0c;涌现了一些AI模特换装的前端工具&#xff08;比如weshop网站&#xff09;&#xff0c;他们是怎么实现的呢&#xff1f;使用了什么技术呢&#xff1f;下文我们就来探索一下其实现原理。 总体的实现流程如下&am…

HarmonyOS将程序下载并运行到真机上 (华为手机为例)

前面的文章 我们讲到过一些关于这个预览器的操作 可以在上面看到我们代码的一个整体效果 但其实 这边可以真实的运行在我们自己的手机上 因为你这个预览器再好 还是和实际的手机环境有所偏差 首先 我们要设置一下手机 我们在设置中 找到 关于手机 然后 这下面 有一个 Harmo…

如何使用阿里云虚拟主机和域名设置网站?

本文档将向您展示如何使用阿里云虚拟主机来设置一个新网站&#xff0c;并完成一个域名。如果您按照此处的步骤操作&#xff0c;您将启动并运行一个新网站&#xff0c;可以使用您选择的名称在全球范围内访问&#xff0c;并托管在阿里云平台上。 本文档假设您已经拥有有效的阿里…

uView ui 1x uniapp 表格table行内容长度不一导致高度不统一而出现的不对齐问题

问题 因为td单元格内空长度不定导致行单元格未对齐 解决&#xff1a; 重置td的高度&#xff1a;height:100% 改为height:auto !import <u-table><u-tr v-for"(item,index) in Lineinfo.Cust_Name" ><u-td style"height: auto !important;back…

ABAP2XLSX 的安装和demo

ABAP2XLSX 是一个git上面的很好用的工具&#xff0c;它可以帮助abaper们更方便&#xff0c;更简单的生成各种各样复杂的自定义的excel&#xff0c;以满足各企业的信息化建设 在安装这个之前&#xff0c;请先查看之前的博客&#xff0c;去安装abapgit abap2xlsx地址&#xff1…

vue3通过el-dropdown实现动态菜单切换页面

这是效果图 首先是主页index.vue <template><el-row><el-col :span"20"><!-- 顶部菜单 --><div v-if"showTop"><topmenu /></div><!-- 右侧下方区域动态切换的内容 --><div style"flex: 1;&quo…

Python GUI编程:dearpygui和tkinter的对比与选择详解

概要 随着Python在GUI(图形用户界面)编程中的不断发展&#xff0c;出现了许多优秀的库&#xff0c;如dearpygui和tkinter。 这两个库在许多方面都有所不同&#xff0c;不仅是在功能方面&#xff0c;还在设计哲学和用途上。 本文将对比这两个库&#xff0c;并使用Python代码举…

智能AI问答系统ChatGPT网站系统源码+Midjourney绘画+支持GPT-4-Turbo模型+支持GPT-4图片理解能力

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

Audacity降噪消除视频中杂音

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

面试篇之微服务(二)

目录 服务容灾 21.什么是服务雪崩&#xff1f; 22.什么是服务熔断&#xff1f;什么是服务降级&#xff1f; 什么是服务熔断&#xff1f; 什么是服务降级&#xff1f; 有哪些熔断降级方案实现&#xff1f; 23.Hystrix怎么实现服务容错&#xff1f; 24.Sentinel怎么实现限…

【物联网与大数据应用】Hadoop数据处理

Hadoop是目前最成熟的大数据处理技术。Hadoop利用分而治之的思想为大数据提供了一整套解决方案&#xff0c;如分布式文件系统HDFS、分布式计算框架MapReduce、NoSQL数据库HBase、数据仓库工具Hive等。 Hadoop的两个核心解决了数据存储问题&#xff08;HDFS分布式文件系统&#…

基于YOLOv8深度学习的生活垃圾分类目标检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

SOLIDWORKS 2024新功能之SOLIDWORKS Manage篇

SOLIDWORKS 2024 新功能 SOLIDWORKS Manage篇目录概述 • 在文档预览中测量 • Plenary Web 客户端 CAD 文件预览 • 受影响项目的字段条件 • 任务自动化 • 工作任务燃尽图 • 时间表工作时间 • 材料明细表数量 • 替换 BOM 品项的流程输出 • 向 BOM 添加子条件 一…

为什么 SQL 日志文件很大,我应该如何处理?

SQL Server 日志文件是记录所有数据库事务和修改的事务日志文件。在 SQL 术语中&#xff0c;此日志文件记录对数据库执行的所有 INSERT、UPDATE 和 DELETE 查询操作。 如果数据库处于联机状态或处于恢复状态时日志已满&#xff0c;则 SQL Server 通常会发出 9002 错误。在这种…

脚本格式问题记录

服务器上的一些脚本迁移到其他服务上发生的小问题 问题&#xff1a;执行一个在win10系统编写好的shell脚本&#xff0c;放到Linux上执行报错如下&#xff1a; bash: ./xxx.sh: /bin/bash^M: bad interpreter: No such file or directory 原因&#xff1a;window系统写的脚本&a…

c++——string字符串____迭代器.范围for.修改遍历容量操作

在成为大人的路上喘口气. 目录 &#x1f393;标准库类型string &#x1f393;定义和初始化string对象 &#x1f4bb;string类对象的常见构造 &#x1f4bb;string类对象的不常见构造 &#x1f4bb;读写string对象 &#x1f393; string类对象的修改操作 &#x1f4…

大数据——一文详解数据仓库概念(数据仓库的分层概念和维度建模详解)

1、ods是什么&#xff1f; ods层最好理解&#xff0c;基本上就是数据从源表拉过来&#xff0c;进行etl&#xff0c;比如MySQL映射到Hive&#xff0c;那么到了Hive里面就是ods层。ods全称是 Operational Data Store&#xff0c;操作数据存储——“面向主题的”&#xff0c;数据…