Monday, 24 May 2021

Finding fully visible items in a RecyclerView (Like TikTok and Instagram Story)

So what I have here is a custom recyclerview created to achieve a fullscreen portrait video playing functionality like TikTok and Instagram story. Everything works very well except that the RecyclerView cannot find which item is currently visible everytime. When the recyclerview is scrolled too fast, or the if data is refreshed multiple times without pause using a swiperefreshlayout, the viewholder tag's position becomes incorrect in the former case and -1 in the latter case even though the first item is fully visible. This is the most integral part as this is where the recyclerview decides which video is to be played, as in TikTok or in Instagram Story. The playVideo method is where all the visible-item-calculating takes place. What went wrong? Is there a better solution? Hope you will answer. Regards.

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);
        }
    }
}


from Finding fully visible items in a RecyclerView (Like TikTok and Instagram Story)

No comments:

Post a Comment