wake-up-neo.com

RecyclerView - Wie kann man an einer bestimmten Position ganz nach oben scrollen?

In einer RecyclerView kann ich plötzlich zum oberen Rand eines ausgewählten Elements blättern, indem ich Folgendes verwendet:

((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);

Dieser abrupt bewegt das Objekt an die oberste Position. Ich möchte zum Anfang eines Artikelsreibungslos.

Ich habe auch versucht:

recyclerView.smoothScrollToPosition(position);

es funktioniert jedoch nicht gut, da es das Element nicht an die oben ausgewählte Position bewegt. Es blättert lediglich durch die Liste, bis das Element an der Position sichtbar ist.

76
Tiago

RecyclerView ist erweiterbar, so dass es nicht nötig ist, die LayoutManager (wie droidev vorgeschlagen ) zu subclassieren, um den Bildlauf durchzuführen.

Erstellen Sie stattdessen einfach eine SmoothScroller mit der Einstellung SNAP_TO_START:

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
  @Override protected int getVerticalSnapPreference() {
    return LinearSmoothScroller.SNAP_TO_START;
  }
};

Jetzt legen Sie die Position fest, zu der Sie scrollen möchten:

smoothScroller.setTargetPosition(position);

und übergeben Sie diesen SmoothScroller an den LayoutManager:

layoutManager.startSmoothScroll(smoothScroller);
131
Paul Woitaschek

dazu müssen Sie einen benutzerdefinierten LayoutManager erstellen

public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {

    public LinearLayoutManagerWithSmoothScroller(Context context) {
        super(context, VERTICAL, false);
    }

    public LinearLayoutManagerWithSmoothScroller(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {
        RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class TopSnappedSmoothScroller extends LinearSmoothScroller {
        public TopSnappedSmoothScroller(Context context) {
            super(context);

        }

        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return LinearLayoutManagerWithSmoothScroller.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

verwenden Sie dies für Ihre RecyclerView und rufen Sie smoothScrollToPosition auf.

beispiel:

 recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
 recyclerView.smoothScrollToPosition(position);

dies wird zum Anfang des RecyclerView-Elements der angegebenen Position geführt.

hoffe das hilft.

98
droidev

Wir können es so versuchen

    recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
3
Supto

Die einfachste Möglichkeit, eine RecyclerView zu scrollen, ist wie folgt:

// Define the Index we wish to scroll to.
final int lIndex = 0;
// Assign the RecyclerView's LayoutManager.
this.getRecyclerView().setLayoutManager(this.getLinearLayoutManager());
// Scroll the RecyclerView to the Index.
this.getLinearLayoutManager().smoothScrollToPosition(this.getRecyclerView(), new RecyclerView.State(), lIndex);
3
Mapsy

Dies ist eine Erweiterungsfunktion, die ich in Kotlin geschrieben habe, um sie direkt auf RecyclerView aufzurufen (basierend auf der Antwort von @Paul Woitaschek):

fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
    val smoothScroller = object: LinearSmoothScroller(this.context) {
        override fun getVerticalSnapPreference(): Int {
            return snapMode
        }

        override fun getHorizontalSnapPreference(): Int {
            return snapMode
        }
    }
    smoothScroller.targetPosition = position
    layoutManager?.startSmoothScroll(smoothScroller)
}

Verwenden Sie es so:

myRecyclerView.smoothSnapToPosition(itemPosition)
2
vovahost

ich habe so benutzt:

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
0
Criss

Überschreiben Sie die Funktion compareDyToMakeVisible/berechneDxToMakeVisible in LinearSmoothScroller, um die Y/X-Versatzposition zu implementieren 

override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
    return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}
0
user2526517

Wahrscheinlich ist der Ansatz von @droidev der richtige, aber ich möchte nur etwas anderes veröffentlichen, das im Grunde den gleichen Job macht und keine Erweiterung des LayoutManagers erfordert.

Ein HINWEIS hier - das wird gut funktionieren, wenn Ihr Artikel (der, den Sie am oberen Rand der Liste scrollen möchten) auf dem Bildschirm angezeigt wird und Sie ihn einfach automatisch nach oben scrollen möchten. Dies ist nützlich, wenn das letzte Element in Ihrer Liste über eine Aktion verfügt, die neue Elemente in derselben Liste hinzufügt und Sie den Benutzer auf die neu hinzugefügten Elemente konzentrieren möchten:

int recyclerViewTop = recyclerView.getTop();
int positionTop = recyclerView.findViewHolderForAdapterPosition(positionToScroll) != null ? recyclerView.findViewHolderForAdapterPosition(positionToScroll).itemView.getTop() : 200;
final int calcOffset = positionTop - recyclerViewTop; 
//then the actual scroll is gonna happen with (x offset = 0) and (y offset = calcOffset)
recyclerView.scrollBy(0, offset);

Die Idee ist einfach: 1. Wir müssen die oberste Koordinate des Recyclerview-Elements ermitteln. 2. Wir müssen die obere Koordinate des Ansichtselements ermitteln, das wir nach oben scrollen möchten. 3. Am Ende mit dem berechneten Offset müssen wir das tun 

recyclerView.scrollBy(0, offset);

200 ist nur ein Beispiel für einen hart codierten Integer-Wert, den Sie verwenden können, wenn das Viewholder-Element nicht vorhanden ist, da dies ebenfalls möglich ist.

0
Sniper