Java 在RecyclerView中查找完全可见的项目(如TikTok和Instagram故事)
因此,我这里有一个定制的recyclerview,用于实现TikTok和Instagram story等全屏人像视频播放功能。除了RecyclerView每次都找不到当前可见的项目外,其他一切都很好。如果recyclerview滚动过快,或者使用swiperefreshlayout多次刷新if数据而不暂停,则在前一种情况下viewholder标记的位置将不正确,在后一种情况下,即使第一项完全可见,viewholder标记的位置也将变为-1。这是最重要的部分,因为这是recyclerview决定播放哪个视频的地方,就像在TikTok或Instagram故事中一样。playVideo方法是进行所有可见项计算的地方。出了什么问题?有更好的解决办法吗?希望你能回答。问候Java 在RecyclerView中查找完全可见的项目(如TikTok和Instagram故事),java,android,android-recyclerview,Java,Android,Android Recyclerview,因此,我这里有一个定制的recyclerview,用于实现TikTok和Instagram story等全屏人像视频播放功能。除了RecyclerView每次都找不到当前可见的项目外,其他一切都很好。如果recyclerview滚动过快,或者使用swiperefreshlayout多次刷新if数据而不暂停,则在前一种情况下viewholder标记的位置将不正确,在后一种情况下,即使第一项完全可见,viewholder标记的位置也将变为-1。这是最重要的部分,因为这是recyclerview决定播
public class TiktokRecyclerview extends RecyclerView {
int playPosition = - 1;
boolean scrollingUp = false;
int targetPosition;
int currentPosition;
Context context;
TiktokViewHolder holder;
public TiktokRecyclerview (@NonNull Context context) {
super(context);
init(context);
}
public TiktokRecyclerview (@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(final Context context) {
this.context = context;
addOnScrollListener(new OnScrollListener () {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
scrollingUp = dy > 0;
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(context);
}
}
});
}
private void playVideo(Context context) {
if (!scrollingUp) {
targetPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findLastVisibleItemPosition();
} else {
targetPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findFirstVisibleItemPosition();
}
if (targetPosition != playPosition) { // Checks whether source and destination scroll item are same
playPosition = targetPosition;
if (!scrollingUp) {
currentPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findLastCompletelyVisibleItemPosition();
} else {
currentPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findFirstCompletelyVisibleItemPosition();
}
View child = getChildAt (currentPosition);
if (child == null) {
return;
}
if (child.getTag() == null) {
return;
}
holder = (TiktokViewHolder) child . getTag ();
Log.d(TAG, "" + holder);
}
}
}
不知道你为什么在RecyclerView中使用vh标签,因为现在它们有了ViewHolder 但是,您可以从
View child=getChildAt(currentPosition)开始删除所有代码代码>并替换为:
holder=(RVAdapter.TiktokViewHolder)查找布局位置(currentPosition)的查看文件夹代码>
所以你的代码应该是:
...
...
if (targetPosition != playPosition) { // Checks whether source and destination scroll item are same
playPosition = targetPosition;
if (!scrollingUp) {
currentPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findLastCompletelyVisibleItemPosition();
} else {
currentPosition =
((androidx.recyclerview.widget.LinearLayoutManager) Objects . requireNonNull (getLayoutManager())).findFirstCompletelyVisibleItemPosition();
}
//You may need to check if currentPosition is valid
if (currentPosition < 0 || currentPosition >= getChildCount()) return;
holder = (RVAdapter.TiktokViewHolder) findViewHolderForLayoutPosition(currentPosition);
Log.d(TAG, "" + holder);
}
}
。。。
...
如果(targetPosition!=playPosition){//检查源和目标滚动项是否相同
播放位置=目标位置;
如果(!scrollingUp){
当前位置=
((androidx.recyclerview.widget.LinearLayoutManager)对象.requireNonNull(getLayoutManager()).findLastCompletelyVisibleItemPosition();
}否则{
当前位置=
((androidx.recyclerview.widget.LinearLayoutManager)对象.requireNonNull(getLayoutManager()).findFirstCompletelyVisibleItemPosition();
}
//您可能需要检查currentPosition是否有效
if(currentPosition<0 | | currentPosition>=getChildCount())返回;
holder=(RVAdapter.TiktokViewHolder)查找布局位置(currentPosition)的查看文件夹;
日志d(标签“+”持有人);
}
}
这将为您提供完全可见的确切位置谢谢您的回答。但我听说FindViewHolder for LayoutPosition不稳定,可能会抛出nullpointer异常。我应该继续吗?我试过使用你的代码,但现在它根本不起作用。它只播放第一个视频,当我向下滚动时,它不会检测到更改。第一:findViewHolderForLayoutPosition
不会有任何问题,尤其是在scroll\u STATE\u IDLE
STATE之后调用时,因为视图是可见/渲染的,并且ViewHolder应该存在:此解决方案仅在指定位置获得适当的ViewHolder,它与更改检测无关。。。除非currentPosition
无效(检查行块),否则仅当SwiperFresh以快速刷新多次时才会发生。有没有办法阻止用户刷新过快?我现在唯一能想到的方法就是删除当前的recyclerview,并在每次刷新后添加一个新的。这是个好主意吗?我假设这个bug与recyclerview代码无关,而是因为快速刷新。