Saya ingin membahas lebih lengkap masalah durasi gulir , yang, jika Anda memilih jawaban sebelumnya, sebenarnya akan bervariasi secara dramatis (dan tidak dapat diterima) sesuai dengan jumlah pengguliran yang diperlukan untuk mencapai posisi target dari posisi saat ini.
Untuk mendapatkan durasi gulir yang seragam, kecepatan (piksel per milidetik) harus memperhitungkan ukuran masing-masing item - dan bila item tersebut berdimensi non-standar maka tingkat kompleksitas yang sama sekali baru ditambahkan.
Ini mungkin alasan mengapa pengembang RecyclerView menggunakan keranjang yang terlalu keras untuk aspek vital pengguliran yang mulus ini.
Dengan asumsi Anda menginginkan durasi scroll semi-seragam , dan daftar Anda berisi item semi-seragam maka Anda memerlukan sesuatu seperti ini.
/** 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: Saya mengutuk pada hari saya mulai tanpa pandang bulu mengubah ListView ke RecyclerView .
protected int getHorizontalSnapPreference() { return LinearSmoothScroller.SNAP_TO_START; }
. Selanjutnya saya harus menerapkan metode abstrakpublic PointF computeScrollVectorForPosition(int targetPosition) { return layoutManager.computeScrollVectorForPosition(targetPosition); }
.