Ich möchte mehr vollständig das Problem der Adresse Scroll Dauer , die, sollten Sie eine frühere Antwort wählen, wird in der Tat variiert dramatisch (und unakzeptabel) entsprechend der erforderlichen Menge des Scrollens der Zielposition von der aktuellen Position zu erreichen.
Um eine einheitliche Bildlaufdauer zu erhalten, muss die Geschwindigkeit (Pixel pro Millisekunde) die Größe jedes einzelnen Elements berücksichtigen - und wenn die Elemente nicht standardmäßige Abmessungen haben, wird eine völlig neue Komplexität hinzugefügt.
Dies könnte der Grund sein, warum die RecyclerView- Entwickler den zu harten Korb für diesen wichtigen Aspekt des reibungslosen Bildlaufs bereitgestellt haben .
Unter der Annahme , dass Sie einen wollen halb einheitliche Scroll - Dauer, und dass Ihre Liste enthält halb einheitliche Elemente dann werden Sie so etwas wie dieses benötigen.
/** Smoothly scroll to specified position allowing for interval specification. <br>
* Note crude deceleration towards end of scroll
* @param rv Your RecyclerView
* @param toPos Position to scroll to
* @param duration Approximate desired duration of scroll (ms)
* @throws IllegalArgumentException */
private static void smoothScroll(RecyclerView rv, int toPos, int duration) throws IllegalArgumentException {
int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000; // See androidx.recyclerview.widget.LinearSmoothScroller
int itemHeight = rv.getChildAt(0).getHeight(); // Height of first visible view! NB: ViewGroup method!
itemHeight = itemHeight + 33; // Example pixel Adjustment for decoration?
int fvPos = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
int i = Math.abs((fvPos - toPos) * itemHeight);
if (i == 0) { i = (int) Math.abs(rv.getChildAt(0).getY()); }
final int totalPix = i; // Best guess: Total number of pixels to scroll
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(rv.getContext()) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
@Override protected int calculateTimeForScrolling(int dx) {
int ms = (int) ( duration * dx / (float)totalPix );
// Now double the interval for the last fling.
if (dx < TARGET_SEEK_SCROLL_DISTANCE_PX ) { ms = ms*2; } // Crude deceleration!
//lg(format("For dx=%d we allot %dms", dx, ms));
return ms;
}
};
//lg(format("Total pixels from = %d to %d = %d [ itemHeight=%dpix ]", fvPos, toPos, totalPix, itemHeight));
smoothScroller.setTargetPosition(toPos);
rv.getLayoutManager().startSmoothScroll(smoothScroller);
}
PS: Ich verfluche den Tag, an dem ich angefangen habe , ListView wahllos in RecyclerView zu konvertieren .
protected int getHorizontalSnapPreference() { return LinearSmoothScroller.SNAP_TO_START; }
. Außerdem musste ich die abstrakte Methode implementierenpublic PointF computeScrollVectorForPosition(int targetPosition) { return layoutManager.computeScrollVectorForPosition(targetPosition); }
.