wake-up-neo.com

Wie scrollen Sie zum Ende einer RecyclerView? scrollToPosition funktioniert nicht

Ich möchte nach dem Laden der Aktivität zum Ende der RecyclerView-Liste scrollen.

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(...) löst eine Ausnahme aus, in RecyclerView nicht unterstützt zu werden, und conversationView.scrollToPosition(...) scheint nichts zu tun.

Nach dem obigen Codeblock habe ich hinzugefügt

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

was nicht funktioniert Es gibt 30 Elemente in GENERIC_MESSAGE_LIST.

118
waylaidwanderer

Setzen Sie einfach setStackFromEnd=true oder setReverseLayout=true, damit LLM Elemente vom Ende aus anordnet.

Der Unterschied zwischen diesen beiden besteht darin, dass setStackFromEnd die Ansicht so einstellen wird, dass das letzte Element angezeigt wird. Die Layoutrichtung bleibt dabei gleich. (In einer horizontalen Recycler-Ansicht von links nach rechts wird also das letzte Element angezeigt, und beim Scrollen nach links werden die früheren Elemente angezeigt.)

Während setReverseLayout die Reihenfolge der vom Adapter hinzugefügten Elemente ändert. Das Layout beginnt mit dem letzten Element, das sich in einer LTR-Recycler-Ansicht am weitesten links befindet. Wenn Sie nach rechts scrollen, werden die vorherigen Elemente angezeigt.

Probe:

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

Siehe Dokumentation für Details.

167
yigit

Ich habe mir diesen Beitrag angesehen, um die Antwort zu finden, aber ... Ich glaube, jeder in diesem Beitrag hatte das gleiche Szenario wie ich: scrollToPosition() wurde aus einem offensichtlichen Grund völlig ignoriert.

Was ich benutzt habe

recyclerView.scrollToPosition(items.size());

... wasARBEITETE?

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

Ich weiß, dass es zu spät ist, hier zu antworten, dennoch, wenn jemand wissen möchte, dass die Lösung unten ist

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

So scrollen Sie von einer beliebigen Position in der Recyclingübersicht nach unten

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

Wenn Sie setAdapter aufrufen, werden Elemente auf dem Bildschirm nicht sofort angeordnet und positioniert (dies erfordert einen einzelnen Layout-Durchlauf). Daher hat Ihr Aufruf scrollToPosition() keine tatsächlichen Elemente, zu denen Sie beim Aufruf blättern können.

Stattdessen sollten Sie einen ViewTreeObserver.OnGlobalLayoutListener registrieren (über addOnGlobalLayoutListner () aus einer von conversationView.getViewTreeObserver() erstellten ViewTreeObserver), die Ihre scrollToPosition() bis nach dem ersten Layout-Durchlauf verzögert:

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

Fügen Sie diesen Code nach dem Senden der Nachricht und vor dem Abrufen der Nachricht vom Server hinzu

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

und

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

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

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

der obige Code funktioniert, ist aber nicht glatt und nicht cool.

4
Yuki Yoshida

Wenn Sie einen mit recyclerView verbundenen Adapter haben, tun Sie dies einfach.

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

4
Wasim Amin

Lösung für Kotlin :

unter dem Code anwenden, nachdem "recyclerView.adapter" oder "recyclerView.adapter.notifyDataSetChanged ()" eingestellt wurde

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

In meinem Fall, in dem Ansichten nicht die gleiche Höhe haben, konnte mit dem Aufruf von scrollToPosition im LayoutManager wirklich nach ganz unten geblättert und der letzte Punkt vollständig angezeigt werden:

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

Roc Antwort ist eine große Hilfe. Ich möchte einen kleinen Block hinzufügen:

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

Das funktioniert perfekt für mich:

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

In Kotlin:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }

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

Versuchte eine Methode von @ galex , es funktionierte bis zum Refactoring. Also habe ich eine Antwort von @ yanchenko verwendet und ein bisschen geändert. Das liegt wahrscheinlich daran, dass ich das Scrollen von onCreateView() aufgerufen habe, wo eine Fragmentansicht erstellt wurde (und wahrscheinlich nicht die richtige Größe hatte).

private fun scrollPhotosToEnd(view: View) {
    view.recycler_view.viewTreeObserver.addOnGlobalLayoutListener(object :
        ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                view.recycler_view.viewTreeObserver.removeOnGlobalLayoutListener(this)
            } else {
                @Suppress("DEPRECATION")
                view.recycler_view.viewTreeObserver.removeGlobalOnLayoutListener(this)
            }
            adapter?.itemCount?.takeIf { it > 0 }?.let {
                view.recycler_view.scrollToPosition(it - 1)
            }
        }
    })
}

Sie können auch eine Prüfung von viewTreeObserver.isAlive wie in https://stackoverflow.com/a/39001731/291414 hinzufügen.

0
CoolMind

dieser Code wird Ihnen den neuesten Beitrag zuerst geben. Ich denke, diese Antwort ist hilfreich. 

    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

Nur Ians Antwort konnte meine RecyclerView an eine bestimmte Position verschieben. Die RecyclerView konnte jedoch nicht weiter scrollen, wenn ich scrollToPosition() verwendete. smoothScrollToPosition() hat funktioniert, aber die anfängliche Animation wurde zu langsam, wenn die Liste lang war. Der Grund war, dass der Listener nicht entfernt wurde. Ich habe den folgenden Code verwendet, um die aktuelle ViewTreeObserver zu entfernen, und es funktionierte als Zauber.

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

Erstmaliges Scrollen beim erstmaligen Aufrufen der Recycler-Ansicht mit linearLayoutManager.scrollToPositionWithOffset (messageHashMap.size () - 1, Minus für das Scrollen nach unten für das Scrollen nach oben, positiver Wert);

wenn die Ansicht sehr hoch ist, wird für die Ansicht von oben ein bestimmter Versatz für die Bildlaufposition verwendet

int overallXScroldl = chatMessageBinding.rvChat.computeVerticalScrollOffset ();chatMessageBinding.rvChat.smoothScrollBy (0, Math.abs (overallXScroldl));

0
Dishant Kawatra