项目需求
加载列表视频,点击视频可播放,当列表滑动的时候,播放视频的item不在界面上的时候,显示小窗播放。
如图所示:
视频列表
视频播放
视频滑动,窗口播放
需求实现
使用开源库【GSYVideoPlayer】播放器框架
开源项目链接: GSYVideoPlayer
1.引入依赖
//视频播放器GSYVideoPlayer框架
implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-java:v8.3.4-release-jitpack'
//是否需要ExoPlayer模式
implementation 'com.github.CarGuo.GSYVideoPlayer:GSYVideoPlayer-exo2:v8.3.4-release-jitpack'
//是否需要AliPlayer模式
implementation 'com.github.CarGuo.GSYVideoPlayer:GSYVideoPlayer-aliplay:8.3.4-release-jitpack'
//更多ijk的编码支持
implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-ex_so:v8.3.4-release-jitpack'
2.创建一个TestActivity页面布局
<?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="match_parent"
tools:context=".test.TestActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
android:overScrollMode="never"
android:scrollbars="none" />
<FrameLayout
android:id="@+id/ftest_video_full"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
3.创建TestActivity
class TestActivity : AppCompatActivity() {
inner class TestBean(
var httpStr: String
)
companion object {
const val TAG = "TestActivity"
}
private lateinit var testAdapter: TestAdapter
private var homeList: MutableList<TestBean> = ArrayList()
private lateinit var layoutManager: LinearLayoutManager
private lateinit var smallVideoHelper: GSYVideoHelper
private lateinit var gsySmallVideoHelperBuilder: GSYVideoHelper.GSYVideoHelperBuilder
private var lastVisibleItem = 0
private var firstVisibleItem = 0
private lateinit var binding: ActivityTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTestBinding.inflate(layoutInflater)
setContentView(binding.root)
for (index in 0 until 20) {
homeList.add(
TestBean(
"https://vd3.bdstatic.com/mda-ic7ix5vebpup50sj/sc/mda-ic7ix5vebpup50sj.mp4?v_from_s=hkapp-haokan-hna&auth_key=1676626834-0-0-75b44d972c3736dc9b8bd5e11ce8c124&bcevod_channel=searchbox_feed&pd=1&cd=0&pt=3&logid=0634011548&vid=2616835831019383631&abtest=&klogid=0634011548"
)
)
}
layoutManager = LinearLayoutManager(this)
testAdapter = TestAdapter(this, homeList)
binding.rvTest.layoutManager = layoutManager
binding.rvTest.adapter = testAdapter
smallVideoHelper = GSYVideoHelper(this, NormalGSYVideoPlayer(this))
smallVideoHelper.setFullViewContainer(binding.ftestVideoFull)
//配置
gsySmallVideoHelperBuilder = GSYVideoHelper.GSYVideoHelperBuilder()
gsySmallVideoHelperBuilder
.setHideActionBar(true)
.setHideStatusBar(true)
.setNeedLockFull(true)
.setCacheWithPlay(true)
.setAutoFullWithSize(true)
.setShowFullAnimation(true)
.setLockLand(true).setVideoAllCallBack(object : GSYSampleCallBack() {
override fun onQuitSmallWidget(url: String, vararg objects: Any) {
super.onQuitSmallWidget(url, *objects)
//大于0说明有播放,//对应的播放列表TAG
if (smallVideoHelper.playPosition >= 0 && smallVideoHelper.playTAG == RecyclerItemViewHolder.TAG) {
//当前播放的位置
val position = smallVideoHelper.playPosition
//不可视的是时候
if (position < firstVisibleItem || position > lastVisibleItem) {
//释放掉视频
smallVideoHelper.releaseVideoPlayer()
testAdapter.notifyDataSetChanged()
}
}
}
})
smallVideoHelper.setGsyVideoOptionBuilder(gsySmallVideoHelperBuilder)
testAdapter.setVideoHelper(smallVideoHelper, gsySmallVideoHelperBuilder)
binding.rvTest.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
lastVisibleItem = layoutManager.findLastVisibleItemPosition()
//大于0说明有播放,//对应的播放列表TAG
if (smallVideoHelper.playPosition >= 0 && smallVideoHelper.playTAG == RecyclerItemViewHolder.TAG) {
//当前播放的位置
val position = smallVideoHelper.playPosition
//不可视的时候
if (position < firstVisibleItem || position > lastVisibleItem) {
//如果是小窗口就不需要处理
if (!smallVideoHelper.isSmall && !smallVideoHelper.isFull) {
//小窗口
val size = CommonUtil.dip2px(this@TestActivity, 150f)
//actionbar为true才不会掉下面去
smallVideoHelper.showSmallVideo(Point(size, size), true, true)
}
} else {
if (smallVideoHelper.isSmall) {
smallVideoHelper.smallVideoToNormal()
}
}
}
}
})
}
override fun onDestroy() {
super.onDestroy()
smallVideoHelper.releaseVideoPlayer()
GSYVideoManager.releaseAllVideos()
}
4.清单文件配置,这个需要配置,不然当视频播放的时候全屏显示会出现问题崩溃
<activity
android:name=".TestActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
5.item 的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/test_item_container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="8dp"
android:background="#FFFFFF"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/test_item_btn"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@drawable/video_click_play_selector" />
</RelativeLayout>
6.TestAdapter
public class TestAdapter extends RecyclerView.Adapter {
private final static String TAG = "RecyclerHomeAdapter";
private final Context context;
private GSYVideoHelper smallVideoHelper;
private GSYVideoHelper.GSYVideoHelperBuilder gsyVideoHelperBuilder;
private final List<TestActivity.TestBean> itemDataList;
public TestAdapter(Context context, List<TestActivity.TestBean> itemDataList) {
this.itemDataList = itemDataList;
this.context = context;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_test, parent, false);
return new TestItemViewHolder(context, view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
TestItemViewHolder recyclerItemViewHolder = (TestItemViewHolder) holder;
recyclerItemViewHolder.setVideoHelper(smallVideoHelper, gsyVideoHelperBuilder);
recyclerItemViewHolder.setRecyclerBaseAdapter(this);
recyclerItemViewHolder.onBind(position, itemDataList);
}
@Override
public int getItemCount() {
return itemDataList.size();
}
public GSYVideoHelper getVideoHelper() {
return smallVideoHelper;
}
public void setVideoHelper(GSYVideoHelper smallVideoHelper, GSYVideoHelper.GSYVideoHelperBuilder gsyVideoHelperBuilder) {
this.smallVideoHelper = smallVideoHelper;
this.gsyVideoHelperBuilder = gsyVideoHelperBuilder;
}
}
7.TestItemViewHolder
public class TestItemViewHolder extends RecyclerItemBaseHolder {
public final static String TAG = "RecyclerItemViewHolder";
private FrameLayout frameLayout;
private ImageView imaPlay;
private ImageView imaBackground;
private GSYVideoHelper smallVideoHelper;
private GSYVideoHelper.GSYVideoHelperBuilder gsyVideoHelperBuilder;
public TestItemViewHolder(Context context, @NonNull View itemView) {
super(itemView);
frameLayout = itemView.findViewById(R.id.test_item_container);
imaPlay = itemView.findViewById(R.id.test_item_btn);
imaBackground = new ImageView(context);
}
public void onBind(final int position, List<TestActivity.TestBean> list) {
imaBackground.setScaleType(ImageView.ScaleType.CENTER_CROP);
imaBackground.setImageResource(R.mipmap.ic_dog);
smallVideoHelper.addVideoPlayer(position, imaBackground, TAG, frameLayout, imaPlay);
imaPlay.setOnClickListener(new View.OnClickListener() {
@SuppressLint("NotifyDataSetChanged")
@Override
public void onClick(View v) {
smallVideoHelper.setPlayPositionAndTag(position, TAG);
getRecyclerBaseAdapter().notifyDataSetChanged();
gsyVideoHelperBuilder.setSurfaceErrorPlay(true)
.setUrl(list.get(position).getHttpStr());
smallVideoHelper.startPlay();
}
});
}
public void setVideoHelper(GSYVideoHelper smallVideoHelper, GSYVideoHelper.GSYVideoHelperBuilder gsySmallVideoHelperBuilder) {
this.smallVideoHelper = smallVideoHelper;
this.gsyVideoHelperBuilder = gsySmallVideoHelperBuilder;
}
}
8.RecyclerItemBaseHolder
public class RecyclerItemBaseHolder extends RecyclerView.ViewHolder {
RecyclerView.Adapter adapter;
public RecyclerItemBaseHolder(@NonNull View itemView) {
super(itemView);
}
public RecyclerView.Adapter getRecyclerBaseAdapter() {
return adapter;
}
public void setRecyclerBaseAdapter(RecyclerView.Adapter recyclerBaseAdapter) {
this.adapter = recyclerBaseAdapter;
}
}
OVER