Tôi muốn giải quyết đầy đủ hơn vấn đề về thời lượng cuộn , nếu bạn chọn bất kỳ câu trả lời nào sớm hơn, trên thực tế sẽ thay đổi đáng kể (và không thể chấp nhận được) theo số lượng cuộn cần thiết để đạt được vị trí mục tiêu từ vị trí hiện tại.
Để có được thời lượng cuộn đồng nhất, tốc độ (pixel trên mili giây) phải tính đến kích thước của từng mục riêng lẻ - và khi các mục có kích thước không chuẩn thì một mức độ phức tạp hoàn toàn mới sẽ được thêm vào.
Đây có thể là lý do tại sao các nhà phát triển RecyclerView đã triển khai giỏ quá khó cho khía cạnh quan trọng này của việc cuộn mượt mà.
Giả sử rằng bạn muốn thời lượng cuộn bán đồng nhất và danh sách của bạn chứa các mục bán đồng nhất thì bạn sẽ cần một cái gì đó như thế này.
/** 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);
}
Tái bút: Tôi nguyền rủa ngày tôi bắt đầu chuyển đổi bừa bãi ListView thành RecyclerView .
protected int getHorizontalSnapPreference() { return LinearSmoothScroller.SNAP_TO_START; }
. Hơn nữa, tôi phải triển khai phương thức trừu tượngpublic PointF computeScrollVectorForPosition(int targetPosition) { return layoutManager.computeScrollVectorForPosition(targetPosition); }
.