最近有个需求,类似于皮皮虾那种列表上有播放器,滑动停止时自动播放可视区域的第一项;
查了一些资料,看了一些大神的博客,受益匪浅,这里也做一个记录,方便以后搬砖;
要实现这个功能,主要需要四部分工作:
1、监听列表的滚动事件,知道什么时候开始滚动和停止滚动;
2、找出可视区域的item,再找出第一项中的播放器;
3、监听移除屏幕的item,及时回收播放器资源;
3、找一个适合的播放器,有些播放器就是不得劲。
直接上代码,
MainActivity.java
- 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.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;
-
- @Override
- protected 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() {
- @Override
- public void onChildViewAttachedToWindow(View view) {
- // item依附到recyclerview中时
- }
-
- @Override
- public void onChildViewDetachedFromWindow(View view) {
- // item从recyclerview中分离时
- 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
- }
-
- @Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- super.onScrollStateChanged(recyclerView, newState);
- switch (newState) {
- case RecyclerView.SCROLL_STATE_IDLE://停止滚动
- autoPlayVideo(recyclerView, VideoTagEnum.TAG_AUTO_PLAY_VIDEO);
- case RecyclerView.SCROLL_STATE_DRAGGING://开始滚动
- case RecyclerView.SCROLL_STATE_SETTLING://滑行中
- default:
- // autoPlayVideo(recyclerView, VideoTagEnum.TAG_PAUSE_VIDEO);//滑动时暂停视频 需要可以加上
- break;
- }
-
- }
-
- @Override
- public 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)方法计算出哪个播放器完全显示出来
- * @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;
- }
- }
-
-
- }
-
- /**
- * 拦截返回键 返回不退出程序
- */
- @Override
- public 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);
- }
- }
-
PlayerAdapter.java
- 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;
-
- public class PlayerAdapter extends RecyclerView.Adapter
{ - private Context context;
-
- public PlayerAdapter(Context context) {
- this.context = context;
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- ViewHolder holder = new ViewHolder(LayoutInflater.from(
- context).inflate(R.layout.item_recyclerview, parent,
- false));
- return holder;
- }
-
- @SuppressLint("LongLogTag")
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- // String url = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
- String url = "https://pointshow.oss-cn-hangzhou.aliyuncs.com/McTk51586843620689.mp4";
- holder.videoplayer.setUp(url, "", JzvdStd.SCREEN_NORMAL);
- holder.videoplayer.setVideoImageDisplayType(1);
- holder.videoplayer.thumbImageView.setScaleType(ImageView.ScaleType.FIT_XY);
- // holder.videoplayer.startVideo();//自动播放 在recyclerview有bug
- Glide.with(holder.videoplayer.getContext()).load("http://jzvd-pic.nathen.cn/jzvd-pic/00b026e7-b830-4994-bc87-38f4033806a6.jpg").
- into(holder.videoplayer.thumbImageView);
-
- }
-
- @Override
- public int getItemCount() {
- return 10;
- }
-
- class ViewHolder extends RecyclerView.ViewHolder {
- private MyJzvdStd videoplayer;
-
- public ViewHolder(View itemView) {
- super(itemView);
- videoplayer = itemView.findViewById(R.id.videoplayer);
- }
- }
- }
activity_main.xml
- "1.0" encoding="utf-8"?>
"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">
-
-
- android:id="@+id/recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
item_recyclerview.xml
- "1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android" - android:layout_width="match_parent"
- android:layout_height="300dp">
-
-
- android:id="@+id/videoplayer"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
-
-
build.gradle 中加上播放器和glide的依赖
- 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'
资源下载链接
https://download.csdn.net/download/msn465780/87131990
好了,又可以愉快玩耍了。
-
相关阅读:
Jmeter性能测试指南
【完美世界】天仙书院偷食也就算了,竟然还偷院长的孙女,美滋滋
Django5+React18前后端分离开发实战04 开发我们的后端服务
zabbix配置95计费
Java中的网络编程------基于Socket的TCP编程和基于UDP的网络编程,netstat指令
数据挖掘案列分析---LightGBM实战贷款违约预测
【云原生&微服务十】SpringCloud之OpenFeign实现服务间请求头数据传递(OpenFeign拦截器RequestInterceptor的使用)
厉害了!有了它,发顶会顶刊拿赛事大奖轻松多了!
Backbone 网络-ResNet v2 详解
低代码开发平台的功能有哪些?低代码“功能清单”一览
-
原文地址:https://blog.csdn.net/msn465780/article/details/128004957