[JAVA] Korrigieren Sie die Stoppposition vonoothScrollToPosition von RecyclerView

Einführung

Wenn ich SmoothScrollToPosition mit RecyclerView verwendet habe, wurde es nur auf halber Strecke angehalten. Dies ist also ein Memo, als ich es überprüft habe.

Annahme

Verwenden Sie LinearLayoutManager Die Bildlaufrichtung ist vertikal

Was ich machen wollte

Ich möchte sicherstellen, dass die Position des Bildlaufstopps oben ist

Standardverhalten

Abhängig von der Bildlaufrichtung kann es nach oben oder unten gehen ...

Interne Umsetzungsuntersuchung

smoothScrollToPosition Die Implementierung im häufig verwendeten LinearLayoutManager sieht folgendermaßen aus.

LinearLayoutManager.java


@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
   LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext());
   //Stellen Sie scroll scrollPosition im Scroller ein
   linearSmoothScroller.setTargetPosition(position);
   //Scrollen Sie mit dem Scroller
   startSmoothScroll(linearSmoothScroller);
}

LinearSmoothScroller erbt von SmoothScroller.

SmoothScroller

SmoothScroller ist eine abstrakte Klasse und enthält eine Methode namens onTargetFound.

SmoothScroller.java


public abstract static class SmoothScroller {
   ...(Abkürzung)
   /**
    * Called when the target position is laid out. This is the last callback SmoothScroller
    * will receive and it should update the provided {@link Action} to define the scroll
    * details towards the target view.
    * @param targetView    The view element which render the target position.
    * @param state         Transient state of RecyclerView
    * @param action        Action instance that you should update to define final scroll action
    *                      towards the targetView
    */
   protected abstract void onTargetFound(View targetView, State state, Action action);
   ...(Abkürzung)
}

SmoothScroller hat einige Rückrufe, aber dieser Rückruf ist der letzte, der benachrichtigt wird und wird aufgerufen, wenn die Zielansicht in das Layout kommt. Was hier zu tun ist, gibt es einen Kommentar dahingehend, dass Sie die als Argument übergebene "Aktion" aktualisieren und die Position verfeinern sollten. Lassen Sie uns nun überprüfen, welche Art von Implementierung speziell in "LinearSmoothScroller" enthalten ist.

LinearSmoothScroller

LinearSmoothScroller.java


@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
    final int dx = calculateDxToMakeVisible(targetView, getHorizontalSnapPreference());
    final int dy = calculateDyToMakeVisible(targetView, getVerticalSnapPreference());
    final int distance = (int) Math.sqrt(dx * dx + dy * dy);
    final int time = calculateTimeForDeceleration(distance);
    if (time > 0) {
        action.update(-dx, -dy, time, mDecelerateInterpolator);
    }
}

Es berechnet den erforderlichen Bildlaufbetrag in x- und y-Richtung und führt action.update aus. Der Inhalt der zu berechnenden Implementierung von berechneDx / DyToMakeVisible ist matschig. Wenn Sie also nur die Kommentare betrachten, sieht es so aus.

LinearSmoothScroller.java


/**
 * Calculates the vertical scroll amount necessary to make the given view fully visible
 * inside the RecyclerView.
 *
 * @param view           The view which we want to make fully visible
 * @param snapPreference The edge which the view should snap to when entering the visible
 *                       area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
 *                       {@link #SNAP_TO_ANY}.
 * @return The vertical scroll amount necessary to make the view visible with the given
 * snap preference.
 */
public int calculateDyToMakeVisible(View view, int snapPreference) {

Es wird angegeben, dass der erforderliche Bildlauf berechnet wird, bevor die gesamte Ansicht des ersten Arguments angezeigt wird. Das zweite Argument gibt die Position an, an der die Ansicht endgültig angezeigt werden soll, und wählen Sie eine der folgenden drei aus.

Wenn man sich die getVerticalSnapPreference ansieht, die das zweite Argument bestimmt, sieht es so aus.

LinearSmoothScroller.java


protected int getVerticalSnapPreference() {
    return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY :
            mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START;
}

Je nach Bildlaufrichtung wird zwischen "SNAP_TO_START" und "SNAP_TO_END" umgeschaltet. Mit anderen Worten, zu diesem Zweck kann dies durch Ändern (Überschreiben) dieser snapPreference erreicht werden.

Fazit

Die Beschreibung ist lang geworden, aber ich habe festgestellt, dass der Code, der tatsächlich implementiert werden sollte, ausreicht, um den Standard-LinearSmoothScroller ein wenig zu erweitern.

CustomLayoutManager.kt


class CustomLayoutManager(context: Context) : LinearLayoutManager(context) {
    override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State?, position: Int) {
        val linearSmoothScroller = object : LinearSmoothScroller(recyclerView.context) {
            override fun getVerticalSnapPreference(): Int = if (reverseLayout) SNAP_TO_END else SNAP_TO_START
        }
        linearSmoothScroller.targetPosition = position
        startSmoothScroll(linearSmoothScroller)
    }
}

Übrigens wird in diesem Beispiel nur "reverseLayout" berücksichtigt, aber ich denke, dass es universell ist, es auch unter Berücksichtigung der Bildlaufrichtung (vertikal / horizontal) zu implementieren.

Recommended Posts

Korrigieren Sie die Stoppposition vonoothScrollToPosition von RecyclerView
Jetzt habe ich die Grundlagen von RecyclerView zusammengefasst
Ein- und Ausklappen des Inhalts der Recycler-Ansicht
Passen Sie an, wie der Inhalt von Recyclerview aufgeteilt wird
Wie ist der nächste Wert des Time-Objekts korrekt?
Ich möchte die Bildlaufposition von UITableView zurückgeben!
Die Welt der Clara-Regeln (2)
Beurteilung des Kalenders
Die Welt der Clara-Regeln (4)
Die Welt der Clara-Regeln (1)
Die Welt der Clara-Regeln (3)
Die Welt der Clara-Regeln (5)
Die Idee der schnellen Sortierung
Die Idee von jQuery
Die richtige Antwort für Geld! Die richtige Antwort für Silber! [Japanische Ausgabe mehrerer Zeilen]