如何让 RecyclerView 平滑滚动?
How to make RecyclerView scroll smoothly?
这更像是一个笼统的问题,但经过大量搜索和尝试后,我无法理解为什么这如此难以实现。 是我能找到但仍然无法实现的最接近的答案。
具体来说,我将 RecyclerView 与 GridLayoutManager 一起使用。我想要的只是网格布局平滑滚动(就像默认的 gallary 应用程序),没什么特别的,但网格布局管理器的默认实现以 'jerky' 方式滚动视图。我尝试从上面 link 实现该方法但未成功。
我也尝试过实现 LinearSmoothScroller,但我不确定如何实现 computeScrollVectorForPosition 方法。 Google's documentation computeScrollVectorForPosition 字面上有 0 个字。
我找到了 this 3 part tutorial,但帮助不大。所以,我想问的是:是否有某种模板代码我们可以在 LinearSmoothScroller 中实现或通过扩展 RecyclerView.SmoothScroller 实现平滑滚动?即使代码取决于网格布局中的项目数和每行项目数,也必须有一些方法可以轻松完成。我在这里遗漏了什么吗?
"jerky" 在 Android 中滚动的典型原因是应用程序在更新 UI 的主应用程序线程上花费了太多时间。在 RecyclerView
的情况下,这意味着在 onBindViewHolder()
或可能在 onCreateViewHolder()
中花费太多时间。每个都需要在亚毫秒内 return,这意味着您不能在其中执行磁盘 I/O 或网络 I/O。
think I found the problem. I am using holder.photo.setImageBitmap(BitmapFactory.decodeFile(itemList.get(position).getAbsolutePath())); on onBindViewHolder() and the image file is around 100kb each with about a dozen images in the list
是的,这将在主应用程序线程上进行磁盘 I/O 和图像解码。这将足够慢以导致 UI 卡顿(即 "jerky" 滚动)。
考虑使用图像加载库,例如 Picasso 或 Universal Image Loader,因为它们可以从位图中异步填充您的 ImageView
。
This sample app 使用 Universal Image Loader 来帮助填充 RecyclerView
(带有 GridLayoutManager
)的内容,数据源是设备上的可用视频。
只需添加这个
animateLayoutChanges = true
在回收站视图中xml
android:animateLayoutChanges="false"
将此添加到您在 Activity
或 Fragment
中声明 RecyclerView
的任何位置
RecyclerView mRecyclerview = (RecyclerView) findViewById(...);
mRecyclerview.setNestedScrollingEnabled(false);
setNestedScrollview(false)
does the work for you.
我刚遇到这个问题,禁用嵌套滚动修复了它。
这样做:
yourRecyclerview.setNestedScrollingEnabled(false);
或者您可以更改定义 RecyclerView 的 xml 文件中的值:
<android.support.v7.widget.RecyclerView
android:id="@+id/yourRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false"/>
我通过覆盖 calculateSpeedPerPixel(DisplayMetrics displayMetrics)
方法使滚动变得平滑:
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
}
}
}
我刚遇到这个问题,我得到了
我把 RecyclerView
放在 ScrollView
所以请永远不要把 RecyclerView
放在 ScrollView
里面,这也可能导致
mLayoutManager.findFirstVisibleItemPosition()
那总是return一个固定值。还要检查
recyclerview.setNestedScrollingEnabled(false);
你需要使用"Picasso"库来异步加载图片,还要确保你加载的图片大小与布局中的图片视图大小相似,使用fit()
函数。此外,如果您在滚动视图中使用回收视图,请确保将 nested scrolling
设置为 false。
我用以上三种方法解决了我的问题
使用此处其他评论所述的库。还要确保您没有将 Recyclerviews 嵌套在 Scrollview 中。这也是我之前不流畅的原因之一。
经过3天的努力,我解决了项目中的平滑滚动问题。
问题是 <layer-list>
可绘制对象设置在 item_user.xml
文件的背景中,因此渲染需要 GPU 时间 这就是滚动不流畅的原因。
不要在适配器项中使用 <layer-list>
或任何其他复杂的可绘制对象。
这更像是一个笼统的问题,但经过大量搜索和尝试后,我无法理解为什么这如此难以实现。
具体来说,我将 RecyclerView 与 GridLayoutManager 一起使用。我想要的只是网格布局平滑滚动(就像默认的 gallary 应用程序),没什么特别的,但网格布局管理器的默认实现以 'jerky' 方式滚动视图。我尝试从上面 link 实现该方法但未成功。
我也尝试过实现 LinearSmoothScroller,但我不确定如何实现 computeScrollVectorForPosition 方法。 Google's documentation computeScrollVectorForPosition 字面上有 0 个字。
我找到了 this 3 part tutorial,但帮助不大。所以,我想问的是:是否有某种模板代码我们可以在 LinearSmoothScroller 中实现或通过扩展 RecyclerView.SmoothScroller 实现平滑滚动?即使代码取决于网格布局中的项目数和每行项目数,也必须有一些方法可以轻松完成。我在这里遗漏了什么吗?
"jerky" 在 Android 中滚动的典型原因是应用程序在更新 UI 的主应用程序线程上花费了太多时间。在 RecyclerView
的情况下,这意味着在 onBindViewHolder()
或可能在 onCreateViewHolder()
中花费太多时间。每个都需要在亚毫秒内 return,这意味着您不能在其中执行磁盘 I/O 或网络 I/O。
think I found the problem. I am using holder.photo.setImageBitmap(BitmapFactory.decodeFile(itemList.get(position).getAbsolutePath())); on onBindViewHolder() and the image file is around 100kb each with about a dozen images in the list
是的,这将在主应用程序线程上进行磁盘 I/O 和图像解码。这将足够慢以导致 UI 卡顿(即 "jerky" 滚动)。
考虑使用图像加载库,例如 Picasso 或 Universal Image Loader,因为它们可以从位图中异步填充您的 ImageView
。
This sample app 使用 Universal Image Loader 来帮助填充 RecyclerView
(带有 GridLayoutManager
)的内容,数据源是设备上的可用视频。
只需添加这个
animateLayoutChanges = true
在回收站视图中xml
android:animateLayoutChanges="false"
将此添加到您在 Activity
或 Fragment
RecyclerView
的任何位置
RecyclerView mRecyclerview = (RecyclerView) findViewById(...);
mRecyclerview.setNestedScrollingEnabled(false);
setNestedScrollview(false)
does the work for you.
我刚遇到这个问题,禁用嵌套滚动修复了它。 这样做:
yourRecyclerview.setNestedScrollingEnabled(false);
或者您可以更改定义 RecyclerView 的 xml 文件中的值:
<android.support.v7.widget.RecyclerView
android:id="@+id/yourRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false"/>
我通过覆盖 calculateSpeedPerPixel(DisplayMetrics displayMetrics)
方法使滚动变得平滑:
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
}
}
}
我刚遇到这个问题,我得到了
我把 RecyclerView
放在 ScrollView
所以请永远不要把 RecyclerView
放在 ScrollView
里面,这也可能导致
mLayoutManager.findFirstVisibleItemPosition()
那总是return一个固定值。还要检查
recyclerview.setNestedScrollingEnabled(false);
你需要使用"Picasso"库来异步加载图片,还要确保你加载的图片大小与布局中的图片视图大小相似,使用fit()
函数。此外,如果您在滚动视图中使用回收视图,请确保将 nested scrolling
设置为 false。
我用以上三种方法解决了我的问题
使用此处其他评论所述的库。还要确保您没有将 Recyclerviews 嵌套在 Scrollview 中。这也是我之前不流畅的原因之一。
经过3天的努力,我解决了项目中的平滑滚动问题。
问题是 <layer-list>
可绘制对象设置在 item_user.xml
文件的背景中,因此渲染需要 GPU 时间 这就是滚动不流畅的原因。
不要在适配器项中使用 <layer-list>
或任何其他复杂的可绘制对象。