RecycleView指定滑动指定位置自动播放视频

tech2022-12-18  104

思路1

1.获取屏幕中要播放的中心点

//限定范围为屏幕一半的上下偏移180 int playTop = CommonUtil.getScreenHeight(getActivity()) / 2 - CommonUtil.dip2px(getActivity(), 180); int playBottom = CommonUtil.getScreenHeight(getActivity()) / 2 + CommonUtil.dip2px(getActivity(), 180); /** * 获取屏幕的高度px * * @param context 上下文 * @return 屏幕高px */ public static int getScreenHeight(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸 windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高 return outMetrics.heightPixels; }

2.获得播放控件在屏幕中的位置

int[] screenPosition = new int[2]; gsyBaseVideoPlayer.getLocationOnScreen(screenPosition); //获取控件高度的一半 int halfHeight = gsyBaseVideoPlayer.getHeight() / 2; //得到控件在屏幕的高度+控件高度的一半 int rangePosition = screenPosition[1] + halfHeight; //中心点在播放区域内 //如果设置要播放的中心点等于当前控件所在的位置时设置播放 if (rangePosition >= rangeTop && rangePosition <= rangeBottom) { inPosition = true; }

思路2

创建一个RecycleView的监听器找到当前屏幕可见的item得到视频广告的item

item 在 recycler view 中的 top

视频控件的高度

int itemViewTop = itemView.getTop(); // item 在 recycler view 中的 top int videoHeight = video.getHeight();// 视频控件的高度

两个值相加根据高度来决定是否播放

// video view 在 recycler view (祖宗容器) 的 top 值 int videoTopYInRecyclerView = itemViewTop + video.getTop(); // 如果video view 顶部有一部分不在recycler view 里面 if (videoTopYInRecyclerView < 0) { // 顶部不在 recycler view 里面的部分小于制定的值,那么播放 if (Math.abs(videoTopYInRecyclerView) <= getPlayOrStopThreshold(videoHeight)) { if(video.isInInPause()){ video.onVideoResume(false); }else if(!video.isInPlayingState()){ video.startPrepare(); } break; }else{ if(video.isInPlayingState()){ video.onVideoPause(); } } }

同理得到item在底部的高度和视频播放器在item的高度来判断是否需要播放

{ int videoBottomYInRecyclerView = itemView.getTop() + video.getBottom(); // video view 在 recycler vie 中的 bot int excess = videoBottomYInRecyclerView - recyclerView.getHeight(); // video view 在 recycler view 中超出部分 // 如果video view 整个都在recycler view 里面或者 video 有一部分已经超出了 recycler view 下面一部分,但是超出部分不足 video view 高度的三分之一 if (excess < getPlayOrStopThreshold(videoHeight)) { if(video.isInInPause()){ video.onVideoResume(false); }else if(!video.isInPlayingState()){ video.startPrepare(); } break; }else{ if(video.isInPlayingState()){ video.onVideoPause(); } } }

完整代码

public class MkVideoScrollListener extends RecyclerView.OnScrollListener { int firstVisibleItem; int lastVisibleItem; LinearLayoutManager linearLayoutManager; private String tag; public MkVideoScrollListener(LinearLayoutManager linearLayoutManager,String tag) { this.linearLayoutManager = linearLayoutManager; this.tag = tag; } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); //大于0说明有播放 if (GSYVideoManager.instance().getPlayPosition() >= 0 && GSYVideoManager.instance().getPlayTag().equals(tag)) { //当前播放的位置 int position = GSYVideoManager.instance().getPlayPosition(); //对应的播放列表TAG if ((position < firstVisibleItem || position > lastVisibleItem)) { //如果滑出去了上面和下面就是否,和今日头条一样 //是否全屏 if(!GSYVideoManager.isFullState((Activity) recyclerView.getContext())) { GSYVideoManager.releaseAllVideos(); recyclerView.getAdapter().notifyItemChanged(position); } } } } @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if(newState == RecyclerView.SCROLL_STATE_IDLE){ play(recyclerView); } } /** * * 从第一可见的position 到最后一个可见的position 挨个遍历 * * 通过 position 找到 对应的item view * * 在通过 item view 找到 holder 对象 * * * 如果这个holder 是一个视频广告的holder * 如果这个item 视频播放器全部可见 那么通过这个item view 找到 对应的播放器控件,然后调用start 播放 * */ public void play(RecyclerView recyclerView){ // 遍历第一个可见 item 和 最后一个可见item 之间的 是否有 视频广告item for (int i = firstVisibleItem; i <= lastVisibleItem; i++) { View itemView = linearLayoutManager.findViewByPosition(i);// 根据 position 找到 item view; RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(itemView); // 更具 item view 找到对应 holder if(holder instanceof MkAutoPlayVideoHolder){ // 如果这个holder 实现了这个接口,意味着这个holder 对应的item 里面的视频会自动播放 MKVideo video = ((MkAutoPlayVideoHolder) holder).getVideoView(); int itemViewTop = itemView.getTop(); // item 在 recycler view 中的 top int videoHeight = video.getHeight();// 视频控件的高度 int videoTopYInRecyclerView = itemViewTop + video.getTop(); // video view 在 recycler view (祖宗容器) 的 top 值 if (videoTopYInRecyclerView < 0) { // 如果video view 顶部有一部分不在recycler view 里面 // 顶部不在 recycler view 里面的部分小于制定的值,那么播放 if (Math.abs(videoTopYInRecyclerView) <= getPlayOrStopThreshold(videoHeight)) { if(video.isInInPause()){ video.onVideoResume(false); }else if(!video.isInPlayingState()){ video.startPrepare(); } break; }else{ if(video.isInPlayingState()){ video.onVideoPause(); } } }else{ int videoBottomYInRecyclerView = itemView.getTop() + video.getBottom(); // video view 在 recycler vie 中的 bot int excess = videoBottomYInRecyclerView - recyclerView.getHeight(); // video view 在 recycler view 中超出部分 // 如果video view 整个都在recycler view 里面或者 video 有一部分已经超出了 recycler view 下面一部分,但是超出部分不足 video view 高度的三分之一 if (excess < getPlayOrStopThreshold(videoHeight)) { if(video.isInInPause()){ video.onVideoResume(false); }else if(!video.isInPlayingState()){ video.startPrepare(); } break; }else{ if(video.isInPlayingState()){ video.onVideoPause(); } } } } } } /** * 返回 video view 上边 或者 下边 垂直方向上在屏幕之外的距离,如果大于这个距离 就停止播放,小于这个距离就自动播放 * 默认是高度的 1/3, 返回 0 表示,只有整个Video View 都在屏幕上可见是才播放。 * @param videoHeight * @return */ public int getPlayOrStopThreshold(int videoHeight){ return 0; } }
最新回复(0)