目录
一、JzvdStd介绍
JzvdStd是一个用于Android平台的开源视频播放器库,它提供了丰富的功能和易于使用的API,使开发者能够快速实现高质量的视频播放功能。
JzvdStd的特点和功能:
- 支持常见的视频格式:JzvdStd支持播放各种常见的视频格式,包括MP4、FLV、MKV、AVI等。
- 自定义界面:JzvdStd提供了丰富的界面定制选项,开发者可以根据自己的需求自定义播放器的外观和交互方式。
- 全屏播放:JzvdStd支持全屏播放模式,用户可以轻松切换到全屏模式以获得更好的观看体验。
- 手势操作:JzvdStd支持手势操作,用户可以通过滑动手势来调节音量、亮度和播放进度。
- 弹幕功能:JzvdStd内置了弹幕功能,用户可以在视频播放过程中发送和接收弹幕信息。
- 网络视频流支持:JzvdStd能够播放网络视频流,开发者可以通过URL链接直接播放在线视频。
JzvdStd常用方法:
setVideoUrl(String url)
:设置要播放的视频源,可以是本地文件路径或网络视频地址。startVideo()
:开始播放视频。pauseVideo()
:暂停视频播放。resumeVideo()
:恢复视频播放。stopVideo()
:停止视频播放,并释放相关资源。releaseAllVideos()
:释放所有正在播放的视频,可用于在切换页面或退出应用时释放资源。enterFullScreen()
:进入全屏播放模式。exitFullScreen()
:退出全屏播放模式。setLoop(boolean loop)
:设置是否循环播放视频。setScreenOnWhilePlaying(boolean screenOn)
:设置在视频播放期间是否保持屏幕亮起。seekTo(int position)
:跳转到指定的播放位置。getCurrentPosition()
:获取当前播放位置。getDuration()
:获取视频总时长。isPlaying()
:判断视频是否正在播放。setOnJzvdStdListener(OnJzvdStdListener listener)
:设置JzvdStd的监听器,用于监听视频播放状态、全屏切换等事件。setVideoImageDisplayType(JzvdStd.SCREEN_IMAGE_DISPLAY_TYPE type)
:设置视频封面图片的显示方式,包括填充、拉伸、原始比例等。setVideoImage(String imageUrl)
:设置视频封面图片的URL地址。setMediaInterface(JZMediaInterface mediaInterface)
:设置JzvdStd使用的媒体接口,可以自定义实现更多功能。
依赖包:
implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
二、JzvdStd使用
补充知识:
PagerSnapHelper是一个辅助类,用于在 RecyclerView 中实现分页滚动效果。它可以与 RecyclerView 搭配使用,实现一次只显示一页内容,并在滚动停止时自动对齐到最近的一页。它可以提供更流畅、直观的滑动体验,并方便地实现横向或纵向的分页展示效果。
主要特点和用途如下:
- 1. 分页滚动:PagerSnapHelper 可以使 RecyclerView 实现类似 ViewPager 的分页滚动效果,即一次只能滚动一页内容。当用户滚动 RecyclerView 时,它会自动将滚动停止的位置对齐到最近的一页。
- 2. 对齐效果:PagerSnapHelper 可以确保 RecyclerView 停止滚动时,当前可见项完全对齐到 RecyclerView 的边界。这样可以让用户更清晰地看到每一页的内容,提供更好的视觉体验。
- 3. 简单易用:PagerSnapHelper 是 Android Support Library 中提供的一个默认实现类,可以轻松地与 RecyclerView 集成使用。只需要创建一个 PagerSnapHelper 对象并调用attachToRecyclerView()方法来关联 RecyclerView,即可实现分页滚动效果。
使用 PagerSnapHelper 的步骤如下:
- 1. 创建 PagerSnapHelper 对象:PagerSnapHelper pagerSnapHelper = new PagerSnapHelper();
- 2. 关联 RecyclerView:pagerSnapHelper.attachToRecyclerView(recyclerView);,其中 recyclerView是你的 RecyclerView 对象。
- 3. 根据需要设置 RecyclerView 的布局管理器(LinearLayoutManager、GridLayoutManager 等)和适配器,以及其他相应的配置。
例子:
MainActivity :
package com.example.jzvdstddemo;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;
import android.os.Bundle;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import cn.jzvd.JzvdStd;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.main_recycler_view)
RecyclerView mVideoRecyclerView;
private List<String> mUrlList;
private PagerSnapHelper mSnapHelper;
private VideoPageAdapter mVideoPageAdapter;
private LinearLayoutManager mLinearLayoutManager;
private int currentPosition = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
init();
mVideoRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE://停止滚动
playVideoInSnapPosition(recyclerView, mSnapHelper, mLinearLayoutManager);
break;
case RecyclerView.SCROLL_STATE_DRAGGING://拖动
break;
case RecyclerView.SCROLL_STATE_SETTLING://惯性滑动
// 发生惯性滑动时停止播放任何正在播放的视频,并释放相关的资源。这可以防止在快速滑动过程中出现视频播放错乱或冲突的情况。
JzvdStd.releaseAllVideos();
break;
}
}
});
}
private void init() {
// 添加网络视频的url
mUrlList = new ArrayList<>();
mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
// HORIZONTAL横着滑动,VERTICAL竖着滑动
mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
mVideoRecyclerView.setLayoutManager(mLinearLayoutManager);
mSnapHelper = new PagerSnapHelper();
mSnapHelper.attachToRecyclerView(mVideoRecyclerView);
mVideoPageAdapter = new VideoPageAdapter(this, mUrlList);
mVideoRecyclerView.setAdapter(mVideoPageAdapter);
}
private void playVideoInSnapPosition(RecyclerView recyclerView, SnapHelper snapHelper, LinearLayoutManager linearLayoutManager) {
// 获取当前固定的视图
View view = snapHelper.findSnapView(linearLayoutManager);
if (view != null) {
// 获取当前位置
int position = recyclerView.getChildAdapterPosition(view);
if (currentPosition != position) {
// 如果切换到了新的固定视图
JzvdStd.releaseAllVideos(); // 释放之前的资源(停止播放上一个视频)
RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view);
if (viewHolder instanceof VideoPageAdapter.VideoViewHolder) {
// 开始播放视频
((VideoPageAdapter.VideoViewHolder) viewHolder).jzVideo.startVideo();
}
}
currentPosition = position;
}
}
@Override
protected void onPause() {
super.onPause();
JzvdStd.releaseAllVideos();
}
}
VideoPageAdapter :
package com.example.jzvdstddemo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import cn.jzvd.JzvdStd;
public class VideoPageAdapter extends RecyclerView.Adapter<VideoPageAdapter.VideoViewHolder> {
private Context context;
private List<String> mUrlList;
public VideoPageAdapter(Context context, List<String> urlList) {
this.context = context;
this.mUrlList = urlList;
}
@NonNull
@Override
public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new VideoViewHolder(LayoutInflater.from(context).inflate(R.layout.video_page,
parent, false));
}
@Override
public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
// 设置视频url和视频标题
holder.jzVideo.setUp(mUrlList.get(position), "第"+ (position + 1)+"视频",
JzvdStd.STATE_NORMAL);
// 如果是第一个视频,就设置自动播放
if (position==0){
holder.jzVideo.startVideo();
}
// 添加视频封面
Glide.with(context).load(mUrlList.get(position)).into(holder.jzVideo.thumbImageView);
}
@Override
public int getItemCount() {
return mUrlList.size();
}
public static class VideoViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.jzVideo)
public JzvdStd jzVideo;
public VideoViewHolder(@NonNull View itemView) {
super(itemView);
// 视图绑定
ButterKnife.bind(this,itemView);
}
}
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/main_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
video_page:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<cn.jzvd.JzvdStd
android:id="@+id/jzVideo"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
依赖:
implementation 'com.jakewharton:butterknife:10.2.3' // 添加此依赖
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' // 添加此规则
implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
implementation 'com.github.bumptech.glide:glide:4.8.0'