Android, wie kann ich die aktuelle Position in der Recycleransicht abrufen, zu der der Benutzer zum Element gescrollt hat
Lesezeit: 6 Minuten
DolDurma
In meinem RecyclerView Ich habe einige Elemente, die der Benutzer scrollen und sehen kann. Jetzt möchte ich diese Position speichern und nach dem Zurückkommen scrollen. Dieser folgende Code gibt immer 0 zurück und ich kann das nicht speichern:
Sie versuchen, die Informationen zum falschen Objekt zu erhalten. Es ist nicht die RecyclerView noch die Adapter Verantwortung, sondern der LayoutManager von RecyclerView.
Anstelle des Generikums ViewTreeObserver.OnScrollChangedListener() Ich würde empfehlen, stattdessen die hinzuzufügen RecyclerView.OnScrollListener und benutze die onScrollStateChanged(RecyclerView recyclerView, int newState) Rückruf, der Ihnen die gibt newStatedu solltest benutzen SCROLL_STATE_IDLE seine Position zu holen. Bedeutung:
Wie Rik van Velzen betonte, müssen Sie wahrscheinlich Ihre Besetzung durchführen LayoutManager zu einem LinearLayoutManager oder GridLayoutManager
(Sie müssen in den richtigen Typ umwandeln, den Sie verwenden), um auf diese zuzugreifen findVisibleXXXX() Methoden.
Auf besagter Callback-Methode. Ich hoffe, ich habe das für Sie klar genug gemacht, Sie können die Dokumentation zu den Klassen hier finden:
Antwort von yigit (Google) auf sichtbare Positionen
linearLayoutManager.scrollToPositionWithOffset(intemIndex, pxFromTop); Wenn es hilfreich war, stimmen Sie bitte meiner Antwort zu.
– Joaquim Ley
7. Juli 2016 um 16:19 Uhr
ist das richtig: recyclerView.scrollToPosition(recyclerViewLastPosition);
– Dol Durma
7. Juli 2016 um 16:37 Uhr
Ja. Sie können smoothScroll auch für visuelle Leckereien verwenden
– Joaquim Ley
28. November 2017 um 14:24 Uhr
Wenn ich die anrufe scrollToPosition es hört nie auf zu scrollen. Irgendwelche Hinweise?
– pamobo0609
9. Mai 2018 um 16:46 Uhr
Möglicherweise müssen Sie den LayoutManager in einen Linear- oder GridLayoutManager usw. umwandeln, wenn Sie getLayoutManager() aufrufen, um findFirstVisibleItemPosition() aufrufen zu können.
– Rik van Velzen
13. Juli 2018 um 8:12 Uhr
Danke für Lösung Joaquim Ley. Dies hilft beim Erstellen recyclerViewhorizontal Pager ohne Verwendung einer Bibliothek.
Drin recyclerView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vocabulary_list);
// Set up the recyclerView with the sections adapter.
mRecyclerView = findViewById(R.id.list);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mRecyclerView.setAdapter(new VocabularyListAdapter<>(vocabularyList));
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE){
int position = getCurrentItem();
onPageChanged(position);
}
}
});
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
}
public boolean hasPreview() {
return getCurrentItem() > 0;
}
public boolean hasNext() {
return mRecyclerView.getAdapter() != null &&
getCurrentItem() < (mRecyclerView.getAdapter().getItemCount()- 1);
}
public void preview() {
int position = getCurrentItem();
if (position > 0)
setCurrentItem(position -1, true);
}
public void next() {
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
if (adapter == null)
return;
int position = getCurrentItem();
int count = adapter.getItemCount();
if (position < (count -1))
setCurrentItem(position + 1, true);
}
private int getCurrentItem(){
return ((LinearLayoutManager)mRecyclerView.getLayoutManager())
.findFirstVisibleItemPosition();
}
private void setCurrentItem(int position, boolean smooth){
if (smooth)
mRecyclerView.smoothScrollToPosition(position);
else
mRecyclerView.scrollToPosition(position);
}
Vielen Dank, lass mich das bitte überprüfen 🙂
– Dol Durma
9. Juni 2018 um 18:58 Uhr
PagerSnapHelper steuert das Scrollen von Element zu Element wie ViewPger
– Vahe Gharibyan
10. Juni 2018 um 23:16 Uhr
Ich bin froh, dass ich helfen konnte, obwohl es so aussieht, als würden Sie jedes Mal Objekte erstellen, wenn Sie es tun RecyclerView berührt wird, nicht sicher, ob dies die leistungsstärkste ist.
– Joaquim Ley
17. Juli 2018 um 13:21 Uhr
Mattia Ferigutti
Dies ist die Erweiterungsfunktion in Kotlin:
fun RecyclerView?.getCurrentPosition() : Int {
return (this?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
}
Sie können es verwenden, indem Sie einfach diese Funktion auf Ihrem aufrufen RecyclerView:
val position = yourRecyclerView.getCurrentPosition()
Es ist nicht ratsam, direkt über zu werfen as und verwenden !! . stattdessen nullfähiges Casting via as? gefolgt von elvis (?:0) ist viel sicherer
– ansh sachdeva
11. Mai 2021 um 16:27 Uhr
Versuchen Sie dies in Kotlin:
myRecyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val offset: Int = myRecyclerView.computeHorizontalScrollOffset()
if (offset % myRecyclerView.width == 0) {
val position: Int = offset / myRecyclerView.width
Log.e("Current position is", position.toString())
}
}
})
P Toles
Ich habe 7 Änderungen in meiner MainActivity vorgenommen und pixelgenaue Ergebnisse erhalten. Meine Recycleransicht erinnert sich IMMER an ihren vorherigen Zustand, wenn sie von einer anderen Aktivität (z. B. DetailActivity) zu ihr zurückkehrt.
Schritt 1: Initialisieren Sie den layoutManager wie folgt:
// Initialize the layout manager
moviePosterLayoutManager = (moviePosterRecyclerView.getLayoutManager() == null) ?
new GridLayoutManager(this, numberOfColumns) : moviePosterRecyclerView.getLayoutManager();
// create a new layoutManager // reuse the existing layoutManager
Schritt 2: Erstellen Sie in Ihrer MainActivity-Klasse eine STATIC-Variable, um Ihren Layout-Manager-Status beim Übergang zwischen Aktivitäten zu speichern:
private static Parcelable layoutManagerState;
Schritt 3: Erstellen Sie diese Konstante auch innerhalb der MainActivity():
public static final String KEY_LAYOUT_MANAGER_STATE = “layoutManagerState”;
Schritt 4: Führen Sie in der onCreate-Methode für Ihre MainActivity den folgenden Test durch (z
protected void onCreate(@Nullable final Bundle savedInstanceState) {....
if (layoutManagerState != null) {
//moviePosterLayoutManager
moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
} else {
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
moviePosterRecyclerView.scrollToPosition(moviePosition);
// the default position
}
Schritt 5: Stellen Sie in Ihrer onSaveInstanceState-Methode sicher, dass Sie Ihren layoutManagerState als parzellierbar wie folgt speichern:
Schritt 7: Denken Sie daran, dass dieser gesamte Code in meiner MainActivity.java-Datei platziert wurde. Es ist wichtig, daran zu denken, dass der LayoutManager für die Aufrechterhaltung der Bildlaufposition der Recycler-Ansicht verantwortlich ist. Daher ist das Speichern des Zustands des LayoutManagers von größter Bedeutung. Der Code könnte modularisiert und in einer benutzerdefinierten Recycleransicht platziert werden, aber ich fand, dass dies für mich einfacher zu implementieren ist.
Das hat bei mir sehr gut funktioniert – Pixel Perfect war richtig.
– Benutzer3479586
4. August 2019 um 20:20 Uhr
Woher bekommen Sie den moviePosition-Wert?
– Benutzer1801605
24. Oktober 2019 um 0:12 Uhr
dieThapa
Für eine ähnliche Anforderung plus einige Aktionen, die bei einer Änderung des Scroll-Status ausgeführt werden mussten, habe ich dies mit einem benutzerdefinierten Scroll-Listener getan:
class OnScrollListener(private val action: () -> Unit) : RecyclerView.OnScrollListener() {
private var actionExecuted: Boolean = false
private var oldScrollPosition: Int = 0
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
when (newState) {
RecyclerView.SCROLL_STATE_DRAGGING -> actionExecuted = false
RecyclerView.SCROLL_STATE_SETTLING -> actionExecuted = false
RecyclerView.SCROLL_STATE_IDLE -> {
val scrolledPosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() ?: return
if (scrolledPosition != RecyclerView.NO_POSITION && scrolledPosition != oldScrollPosition && !actionExecuted) {
action.invoke()
actionExecuted = true
oldScrollPosition = scrolledPosition
}
}
}
}
}
Dies liegt an dem bereits vorhandenen Fehler mit RecyclerView onScroll, der den Rückruf 2-3 Mal oder sogar öfter auslöst. Und wenn eine Aktion ausgeführt werden muss, wird diese am Ende mehrmals ausgeführt.
Das hat bei mir sehr gut funktioniert – Pixel Perfect war richtig.
– Benutzer3479586
4. August 2019 um 20:20 Uhr
Woher bekommen Sie den moviePosition-Wert?
– Benutzer1801605
24. Oktober 2019 um 0:12 Uhr
Tippu Fisal-Sheriff
In meinem Fall brauche ich meine aktuelle Positionsansicht in Aktivität, also erstelle ich eine Rückrufmethode und verwende die folgende Methode.
Fügen Sie diesen Code in die hinzu Adapter Klasse, um die aktuelle Position der Ansicht zu erhalten.
Fügen Sie dies hinzu onBindViewHolder Methode.
holder.imgProductParts.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
onPositionChangeListener.onItemChanged(position);
}
@Override
public void onViewDetachedFromWindow(View v) { }
});
14386100cookie-checkAndroid, wie kann ich die aktuelle Position in der Recycleransicht abrufen, zu der der Benutzer zum Element gescrollt hatyes