Android, wie kann ich die aktuelle Position in der Recycleransicht abrufen, zu der der Benutzer zum Element gescrollt hat

Lesezeit: 6 Minuten

Benutzeravatar von DolDurma
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:

recyclerMarketLists.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        recyclerViewCurrentScrolledPosition = recyclerMarketLists.getScrollY();
        Log.e("Y: ", recyclerViewCurrentSceolledPosition + "");
    }
});

der Logcat:

07-07 18:28:30.919 2124-2124/com.sample.presentationproject E/Y:: 0

Benutzeravatar von Joaquim Ley
Joaquim Ley

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:

yourRecyclerView.getLayoutManager().findFirstVisibleItemPosition();

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:

RecyclerView.OnScrollListener

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 recyclerView horizontal 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

Benutzeravatar von Mattia Ferigutti
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())
        }
    }
})

Benutzeravatar von P Toles
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:

protected void onSaveInstanceState(Bundle outState) {

   layoutManagerState = moviePosterLayoutManager.onSaveInstanceState();

    // Save currently selected layout manager.            
   outState.putParcelable(KEY_LAYOUT_MANAGER_STATE,layoutManagerState);
}

Schritt 6: Platzieren Sie ähnlichen Code in der Methode onResume() von MainActivity:

protected void onResume() {
    super.onResume();


    if (layoutManagerState != null) {
        moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
    }

}

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

Benutzeravatar von theThapa
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

Benutzeravatar des Tippu Fisal Sheriffs
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) { }
        });

1438610cookie-checkAndroid, wie kann ich die aktuelle Position in der Recycleransicht abrufen, zu der der Benutzer zum Element gescrollt hat

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy