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.
Verwenden Sie LinearLayoutManager Die Bildlaufrichtung ist vertikal
Ich möchte sicherstellen, dass die Position des Bildlaufstopps oben ist
Abhängig von der Bildlaufrichtung kann es nach oben oder unten gehen ...
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.
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