it-swarm.com.ru

Как прокрутить до конца RecyclerView? scrollToPosition не работает

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

GENERIC_MESSAGE_LIST = (ArrayList) intent.getExtras().getParcelableArrayList(ConversationsAdapter.EXTRA_MESSAGE);
conversationView = (RecyclerView) findViewById(R.id.list_messages);
conversationView.setHasFixedSize(true);
conversationViewLayoutManager = new LinearLayoutManager(this);
conversationView.setLayoutManager(conversationViewLayoutManager);
conversationViewAdapter = new ConversationAdapter(GENERIC_MESSAGE_LIST, this);
conversationView.setAdapter(conversationViewAdapter);

conversationView.scrollTo(...) выдает исключение о том, что он не поддерживается в RecyclerView, а conversationView.scrollToPosition(...), похоже, ничего не делает.

После вышеупомянутого блока кода я добавил

conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1)

который не работает. В GENERIC_MESSAGE_LIST 30 элементов.

118
waylaidwanderer

Просто установите setStackFromEnd=true или setReverseLayout=true, чтобы LLM планировал элементы с конца.

Разница между этими двумя заключается в том, что setStackFromEnd установит представление для отображения последнего элемента, направление макета останется прежним. (Таким образом, в горизонтальном представлении Recycler слева направо будет показан последний элемент, а при прокрутке влево будут показаны более ранние элементы)

Принимая во внимание, что setReverseLayout изменит порядок элементов, добавленных адаптером. Макет начнется с последнего элемента, который будет самым левым в представлении LTR Recycler, а затем при прокрутке вправо отобразятся более ранние элементы.

Образец:

final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
_listView.setLayoutManager(linearLayoutManager);

Смотрите документацию для деталей.

167
yigit

Я искал этот пост, чтобы найти ответ, но ... я думаю, что все в этом посте столкнулись с тем же сценарием, что и я: scrollToPosition() был полностью проигнорирован по очевидной причине.

Что я использовал?

recyclerView.scrollToPosition(items.size());

... чтоСРАБОТАЛО?

recyclerView.scrollToPosition(items.size() - 1);
292
Roc Boronat

Я знаю, что уже поздно, чтобы ответить здесь, но если кто-то хочет знать решение ниже

conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1);
43
WritingForAnroid

Для прокрутки вниз с любой позиции в обзоре переработчика вниз

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });
11
Muhammad Umair Shafique

Когда вы вызываете setAdapter, это не сразу раскладывает и не позиционирует элементы на экране (что занимает один проход макета), следовательно, ваш вызов scrollToPosition() не имеет фактических элементов для прокрутки, когда вы его вызываете.

Вместо этого вы должны зарегистрировать ViewTreeObserver.OnGlobalLayoutListener (через addOnGlobalLayoutListner () из ViewTreeObserver, созданного conversationView.getViewTreeObserver()), который задерживает вашу scrollToPosition() до окончания первого прохода макета:

conversationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  public void onGlobalLayout() {
    conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size();
    // Unregister the listener to only call scrollToPosition once
    conversationView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

    // Use vto.removeOnGlobalLayoutListener(this) on API16+ devices as 
    // removeGlobalOnLayoutListener is deprecated.
    // They do the same thing, just a rename so your choice.
  }
});
8
ianhanniballake

Добавьте этот код после отправки сообщения и до получения сообщения с сервера

recyclerView.scrollToPosition(mChatList.size() - 1);
7
Shubham Agrawal
class MyLayoutManager extends LinearLayoutManager {

  public MyLayoutManager(Context context) {
    super(context, LinearLayoutManager.VERTICAL, false);
  }

  @Override public void smoothScrollToPosition(RecyclerView recyclerView,
      final RecyclerView.State state, final int position) {

    int fcvip = findFirstCompletelyVisibleItemPosition();
    int lcvip = findLastCompletelyVisibleItemPosition();

    if (position < fcvip || lcvip < position) {
      // scrolling to invisible position

      float fcviY = findViewByPosition(fcvip).getY();
      float lcviY = findViewByPosition(lcvip).getY();

      recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

        int currentState = RecyclerView.SCROLL_STATE_IDLE;

        @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

          if (currentState == RecyclerView.SCROLL_STATE_SETTLING
              && newState == RecyclerView.SCROLL_STATE_IDLE) {

            // recursive scrolling
            smoothScrollToPosition(recyclerView, state, position);
          }

          currentState = newState;
        }

        @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

          int fcvip = findFirstCompletelyVisibleItemPosition();
          int lcvip = findLastCompletelyVisibleItemPosition();

          if ((dy < 0 && fcvip == position) || (dy > 0 && lcvip == position)) {
            // stop scrolling
            recyclerView.setOnScrollListener(null);
          }
        }
      });

      if (position < fcvip) {
        // scroll up

        recyclerView.smoothScrollBy(0, (int) (fcviY - lcviY));
      } else {
        // scroll down

        recyclerView.smoothScrollBy(0, (int) (lcviY - fcviY));
      }
    } else {
      // scrolling to visible position

      float fromY = findViewByPosition(fcvip).getY();
      float targetY = findViewByPosition(position).getY();

      recyclerView.smoothScrollBy(0, (int) (targetY - fromY));
    }
  }
}

а также

MyLayoutManager layoutManager = new MyLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);

RecyclerView.Adapter adapter = new YourAdapter();
recyclerView.setAdapter(adapter);

recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1);

код выше работает, но это не гладко и не круто.

4
Yuki Yoshida

Если у вас есть адаптер, подключенный к recyclerView, просто сделайте это.

mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());

4
Wasim Amin

Решение для Котлин :

применять приведенный ниже код после настройки «recyclerView.adapter» или после «recyclerView.adapter.notifyDataSetChanged ()»

recyclerView.scrollToPosition(recyclerView.adapter.itemCount - 1)
4
chinnuabhi

В моем случае, когда представления не имеют одинаковую высоту, вызов scrollToPosition для LayoutManager сработал, чтобы действительно прокрутить до конца и полностью увидеть последний элемент:

recycler.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1);
3
galex

Ответ Roc - большая помощь. Я хотел бы добавить небольшой блок к нему:

mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
3
abedfar

Это прекрасно работает для меня:

AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);
2
amaresh hiremani

В Котлине:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }

private fun scrollToEnd() =
        (adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition)
1
yanchenko

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

    mInstaList=(RecyclerView)findViewById(R.id.insta_list);
    mInstaList.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

    mInstaList.setLayoutManager(layoutManager);
    layoutManager.setStackFromEnd(true);
    layoutManager.setReverseLayout(true);
0
hasanga lakdinu

Только ответ Яна смог сделать мою прокрутку RecyclerView на указанную позицию. Однако RecyclerView не смог прокрутить потом, когда я использовал scrollToPosition(). smoothScrollToPosition() работал, но первоначальная анимация делала его слишком медленным, когда список был длинным. Причина в том, что слушатель не был удален. Я использовал приведенный ниже код, чтобы удалить текущую переменную ViewTreeObserver, и это сработало.

    mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mRecyclerView.scrollToPosition(mPosition);
            mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });
0
Anky An