Добавление элементов в Endless Scroll RecyclerView с повторным просмотром ReverseLayout

В обычном recyclerview самые новые элементы находятся наверху, и если вы добавляете элемент в recyclerview, он толкает существующие элементы вниз, а новый элемент занимает верхнюю позицию.

В recyclerview reverseLayout самые новые элементы находятся внизу, и если вы добавите элемент в recyclerview, он будет добавлен прямо внизу. Такой вид макета весьма полезен для таких вещей, как комментарии, где вы ожидаете, что последние комментарии будут внизу.

Хорошим примером этого является фид комментариев Facebook, когда вы прокомментируете статус друга, например. Вы можете видеть, что в комментариях есть время, когда они были размещены внизу, а время уменьшается с 12 часов до 10 часов сверху вниз:

facebook comment feed

Реверсивное прохождение довольно легко установить, и я сделал это с помощью этого кода:

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

Я, однако, изо всех сил стараюсь приложить обратный бесконечный прослушиватель прокрутки. Я использую следующий код Vilen из моего вопроса некоторое время назад (Добавление элементов в Endless Scroll RecyclerView с помощью ProgressBar внизу) и его модификацию, чтобы он был включен только для onLoadMoreListener активируйте себя, когда он прокручивается, а не вниз. Вы хотите прокрутить до более старых комментариев:

    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        //if you add on addOnScrollListener, it will cause the scroll listener to be called twice each time you reset your adapter
        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            int firstVisibleItem;
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                final int currentFirstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition();
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

                if(lastVisibleItem > firstVisibleItem)
                {
                    Log.i("SCROLLING UP","TRUE");
                    if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        current_page++;
                        if (onLoadMoreListener != null) {
                            onLoadMoreListener.onLoadMore(current_page);
                        }
                        loading = true;
                    }
                }
                lastVisibleItem=firstVisibleItem;
            }
        });
    }

Когда вызывается onLoadMoreListener, в моем классе activity вызывается следующий код:

    CommentsAdapter.OnLoadMoreListener onLoadMoreListener = new CommentsAdapter.OnLoadMoreListener() {
    @Override
    public void onLoadMore(int current_page) {
        //get the firstCommentId on the list of comments so that we can send it to the server to fetch comments less than that comment id to display in our recyclerview
        firstCommentId = comments.get(0).getId();
        //add empty item for progress bar / wheel and display the progress bar / wheel
        Comment comment = new Comment();
        comment.setViewType(Constants.COMMENT_PROGRESS_BAR);
        comments.add(0, comment);
        mCommentAdapter.notifyItemInserted(0);
        mCommentAdapter.notifyItemRangeChanged(1, comments.size());

        //CODE FOR NETWORK OPERATIONS GOES HERE TO FETCH THE NEXT FEW COMMENTS WHEN SCROLLING UP//
    }
};

Тем не менее, onLoadMoreListener, похоже, вообще не вызывается при прокрутке вверх.

Я также убедился, что у меня было по крайней мере 10 комментариев в моем канале, а 5 было загружено до и еще 5 должны быть загружены при прокрутке вверх.

Что-нибудь знает, что я делаю неправильно с этим обратным OnLoadMoreListener?

EDIT:

Реверсивер reverseLayout на самом деле работает с исходным кодом из Vilen, я загрузил репозиторий github, чтобы показать это:

https://github.com/Winghin2517/ReverseLayoutRecyclerview

По-прежнему возникает проблема, когда активируется onLoadMoreListener - если список комментариев содержит только 3 комментария, и комментариев больше не добавлять, я не хочу, чтобы onLoadMoreListener активировался вообще, когда я изначально просматривать мои комментарии - когда я первый, нажмите на свое приложение, чтобы увидеть комментарии. Прямо сейчас, когда я нажимаю для просмотра своих комментариев, несмотря на то, что в наборе данных есть 3 комментария, индикатор progressBar все еще отображается, и он исчезает через 2 секунды, что, по моему мнению, не является необходимым (см. Github repo, где я это демонстрирую).

Отключение его, когда есть только 3 комментария, также не очень хорошо, поскольку onLoadMoreListener действует как объект swipeToRefresh. Если после пользователя, когда он просматривает фид комментариев, появляется больше комментариев от пользователя, он может прокрутить вниз, и onLoadMoreListener отобразит эти комментарии.

Есть ли способ отключить его, когда корм загружается изначально?

Ответ 1

Саймон: решение, которое я ранее предлагал здесь, отлично работает с обратным расположением без каких-либо изменений. Единственное, что я добавил для обратного макета, - это автоматически прокручивать первый элемент, когда вы показываете его в первый раз, но это зависит от вас. Теперь вернемся к вопросу, который у вас есть. Вы упомянули, что при прокрутке ничего не происходит. так что я предполагаю, что вы инициализируете представление вашего ресайлера в неправильном порядке. Убедитесь, что вы сделали это, как это

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter<>(myDataset, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);

Обратите внимание, что менеджер компоновки сначала создается, а затем вы устанавливаете его, и после этого вы предоставляете адаптер. Дайте мне знать, если это так.

Изменить. Просто воссоздайте это из комментария ниже:

забудьте о том, что у нас есть с onLoadMoreListener, и все прокрутки просто используют стандартный RecyclerView, завернутый в SwipeToRefreshLayout

Ответ 2

Я не очень хотел использовать SwipeToRefreshLayout в конце, потому что он отлично выглядит, когда у вас есть комментарий.

Так что я сделал, это изменить метод onLoadMoreListener, чтобы он обнаруживал, когда активация запускается впервые. Если это первый запуск, мы не хотим отображать индикатор выполнения:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
            if (savedInstanceState == null) {
                                initial = true;
            }
}

Затем мы будем использовать начальную логическую переменную, чтобы определить, только что активировалась активность и отключить индикатор выполнения.

    @Override
    public void onLoadMore(int current_page) {
        //add progress item
        if (initial) {
            //we do not add the progress bar when the activity opens initially so
            //we do nothing. We just change the variable to false so going forward, you will add a progress bar each time you refresh
            initial = false;
        } else {
            comments.add(createProgressBar());
            mCommentAdapter.notifyItemInserted(comments.size()-1);
        }