How to make RecyclerView scroll smoothly?

匿名 (未验证) 提交于 2019-12-03 01:12:01

问题:

This is more like a generic question, but after lot of search and try I am not able to understand why this is so difficult to achieve. This is the closest answer I can find but still unable to implement.

To be specific I am using RecyclerView with GridLayoutManager. All I want is the grid layout to scroll smoothly (like default gallary app) ,nothing fancy, but the default implementation of grid layout manager scrolls the view in a 'jerky' manner. I tried to implement the method from above link but unsuccessfully.

I also tried to implement LinearSmoothScroller but I am not sure how to implement computeScrollVectorForPosition method. Google's documentation on computeScrollVectorForPosition literally has 0 words.

I found this 3 part tutorial, but it was of very little help. So, all I want to ask is: can there be some kind of template code which we can implement in LinearSmoothScroller or by extending RecyclerView.SmoothScroller and achieve smooth scrolling ? Even if the code depends on number of items and items per row in gridlayout, there has to be some method to do it easily. Am I missing something here ?

回答1:

The typical source of "jerky" scrolling in Android is the app taking too much time on the main application thread updating the UI. In the case of RecyclerView, this would mean taking too much time in onBindViewHolder() or possibly in onCreateViewHolder(). Those each need to return in sub-millisecond times, meaning you cannot do disk I/O or network I/O in them.

Yes, that will be doing disk I/O and image decoding on the main application thread. That will be slow enough to cause jank in the UI (i.e., "jerky" scrolling).

Consider using an image loading library, like Picasso or Universal Image Loader, as they can populate your ImageView from the bitmap asynchronously.

This sample app uses Universal Image Loader to help populate the contents of a RecyclerView (with GridLayoutManager), with the data source being the available videos on the device.



回答2:

Add this wherever you have declared RecyclerView in your Activity or Fragment

RecyclerView mRecyclerview = (RecyclerView) findViewById(...); mRecyclerview.setNestedScrollingEnabled(false);

setNestedScrollview(false) does the work for you.



回答3:

I just faced this problem, and disabling nested scroll fixed it. Do it like this:

yourRecyclerview.setNestedScrollingEnabled(false);

Or you can change the value in xml file where you defined RecyclerView:

<android.support.v7.widget.RecyclerView     android:id="@+id/yourRecyclerView"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:nestedScrollingEnabled="false"/>


回答4:

android:animateLayoutChanges="false"


回答5:

I just faced this problem, and i got I put the RecyclerView in ScrollView So please never put the RecyclerView inside the ScrollView that may also cause.

mLayoutManager.findFirstVisibleItemPosition()

That always return a fixed value. And also check

recyclerview.setNestedScrollingEnabled(false);


回答6:

I made the scrolling smooth by overriding the calculateSpeedPerPixel(DisplayMetrics displayMetrics) method:

public class CustomLayoutManager extends LinearLayoutManager {      protected CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {         super(context, orientation, reverseLayout);     }      @Override     public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {         RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());         smoothScroller.setTargetPosition(position);         startSmoothScroll(smoothScroller);     }      private class CenterSmoothScroller extends LinearSmoothScroller {          CenterSmoothScroller(Context context) {             super(context);         }          @Override         public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {             return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);         }          @Override         protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {             return 0.5f; //pass as per your requirement         }     } }


回答7:

just add this

animateLayoutChanges = true 

in recyclerview xml



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!