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
.
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.
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);
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);
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.
}
});
Fügen Sie diesen Code nach dem Senden der Nachricht und vor dem Abrufen der Nachricht vom Server hinzu
recyclerView.scrollToPosition(mChatList.size() - 1);
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.
Wenn Sie einen mit recyclerView verbundenen Adapter haben, tun Sie dies einfach.
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());
Lösung für Kotlin :
unter dem Code anwenden, nachdem "recyclerView.adapter" oder "recyclerView.adapter.notifyDataSetChanged ()" eingestellt wurde
recyclerView.scrollToPosition(recyclerView.adapter.itemCount - 1)
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);
Roc Antwort ist eine große Hilfe. Ich möchte einen kleinen Block hinzufügen:
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
Das funktioniert perfekt für mich:
AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);
In Kotlin:
recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }
private fun scrollToEnd() =
(adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition)
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.
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);
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);
}
});
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));