用recyclerview快速滑动这个滑动好卡,怎么解决

横向的recyclerview拦截了父控件的上下滑动事件怎么办_百度知道如何获取 RecyclerView 的滑动距离?
我需要根据该距离是否大于/小于某个数值来设置 View 的 translation 和 alpha,目前我的代码如下:mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
private int totalDy = 0;
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
totalDy -= dy;
// setTranslation/Alpha here according to totalDy.
如代码所述,totalDy的确保存了 RecyclerView 的滑动距离,但是当我向下滑动 RecyclerView ,之后插入/删除/移动 Item 的时候,totalDy 就变得不精确了——比如我删除Item,那么totalDy就不能再回归到 0了。尝试的第二个方法是令 totalDy = recyclerView.computeVerticalScrollOffset();
然而compute方法计算出的并不是滑动的精确距离,stackOverflow上有答案解释其为 item 的平均高度 * 可见 item 数目。尝试的第三个方法是令totalDy = recyclerView.getChildAt(0).getTop();
依靠第一个item的滑动距离来进行动画的设置,但是根据该方法得出的 totalDy 在滑动到一定程度后清零,猜测是因为真正的第 0 个 Child 被 Recycle 掉了。所以,请问该如何正确地获取 RecyclerView 的滑动距离呢?
滑动到一定程度后清零
猜测是因为 getChildAt(0) 获得的是第一个可见view用LinearLayoutManager的recyclerview测试了一下确实如此,其他类型的尚不清楚=================================================如果LayoutManager用的是LinearLayoutManager 可以用下面的办法/**
* 还能向下滑动多少
private int getDistance() {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
View firstVisibleItem = this.getChildAt(0);
int firstItemPosition = layoutManager.findFirstVisibleItemPosition();
int itemCount = layoutManager.getItemCount();
int recyclerviewHeight = this.getHeight();
int itemHeight = firstVisibleItem.getHeight();
int firstItemBottom = layoutManager.getDecoratedBottom(firstVisibleItem);
return (itemCount - firstItemPosition - 1) * itemHeight - recyclerviewHeight + firstItemBottom;
已滑动的距离:private int getScrolledDistance() {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
View firstVisibleItem = this.getChildAt(0);
int firstItemPosition = layoutManager.findFirstVisibleItemPosition();
int itemHeight = firstVisibleItem.getHeight();
int firstItemBottom = layoutManager.getDecoratedBottom(firstVisibleItem);
return (firstItemPosition + 1) * itemHeight - firstItemBottom;
通过layoutmanager的findviewbyposition查找firstvisibleview和lastvisibleview之后取到left和right之后计算下就得出来了。
注意不要用getchild取view,一定要用layoutmanager的findviewbyposition取!!!
手机写答案太不方便了…
建议监听RecyclerView的addOnScrollListener后自己记录onScrolled的dy,同时给adapter加个registerAdapterDataObserver,监听插入/删除/移动,自己加减前面记录的dy滚动值。
firstVisibleItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
这个是记录item的。楼主贴的那个最好不要用。刚刚试过了。是可以返回y,但是好卡。
提供一个简单的方法来重置totalDy,当插入/删除 的时候调用RecycleView.scrollToPosition(0);totalDy=0.还没有仔细看代码去研究怎么获取RecycleView内item滑动距离。=====割=============================我说下我读源码的结果,关于RecycleView滑动的机制,总结起来有两点:1,RecycleView滑动和布局相对独立。2,RecycleView的滑动分次单独进行。以上两个机制就从根本上阻碍了获取当前的滑动距离,布局的细节是使用铆点,每个view都会根据铆点进行安排自己的位置,这时候没有计算滑动偏移,包括增加view和删除View,增加和删除会根据铆点的位置再次布局,也不会修改滑动偏移,因为他丫的他根本就不用关心滑动,而每次滑动都是计算距离,交给Scroller来滑动Content内的View,我们可以监听滑动接口在没有插入删除的情况下自己计算滑动位置,但是一旦有View动态的增加删除就没有办法了,只能使用楼上的方法了。。。。
尝试的第三个方法是令totalDy = recyclerView.getChildAt(0).getTop();
依靠第一个item的滑动距离来进行动画的设置,但是根据该方法得出的 totalDy 在滑动到一定程度后清零,猜测是因为真正的第 0 个 Child 被 Recycle 掉了。这个方法应该可以,可以创建一个没有内容,不被recycle的viewholder,并且设为第0个child
我遇到了同样的问题,使用 的时候,我想将其中的listview或者gridView换成RecyclerView,但是遇到一个方法不知道怎么转换public int getScrollY(AbsListView view) {
View c = view.getChildAt(0);
if (c == null) {
int firstVisiblePosition = view.getFirstVisiblePosition();
int top = c.getTop();
int headerHeight = 0;
if (firstVisiblePosition &= 1) {
headerHeight = 280;
return -top + firstVisiblePosition * c.getHeight() + headerH
怎样真正的计算出top值?
我也遇到了同样的问题,经过各种折腾总算是勉强算出来了,只是实现方式有点别扭,代码放出来,还请大神多多指点。import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class MyLinearLayoutManager extends LinearLayoutManager {
private RecyclerView.Recycler mRecycler;
public MyLinearLayoutManager(Context context) {
super(context);
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
super.onMeasure(recycler, state, widthSpec, heightSpec);
mRecycler = recycler;
public int getScrollY() {
int scrollY = getPaddingTop();
int firstVisibleItemPosition = findFirstVisibleItemPosition();
if (firstVisibleItemPosition &= 0 && firstVisibleItemPosition & getItemCount()) {
for (int i = 0; i & firstVisibleItemPosition; i++) {
View view = mRecycler.getViewForPosition(i);
if (view == null) {
if (view.getMeasuredHeight() &= 0) {
measureChildWithMargins(view, 0, 0);
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();
scrollY += lp.topMargin;
scrollY += getDecoratedMeasuredHeight(view);
scrollY += lp.bottomMargin;
mRecycler.recycleView(view);
View firstVisibleItem = findViewByPosition(firstVisibleItemPosition);
RecyclerView.LayoutParams firstVisibleItemLayoutParams = (RecyclerView.LayoutParams) firstVisibleItem.getLayoutParams();
scrollY += firstVisibleItemLayoutParams.topMargin;
scrollY -= getDecoratedTop(firstVisibleItem);
return scrollY;
已有帐号?
无法登录?
社交帐号登录10:50 提问
Android RecyclerView滑动卡顿怎么解决?求指点!
使用recyclerview滑动加载更多会出现卡顿的情况,求大神指导这应该怎么解决!
按赞数排序
ViewHolder复用一下试试
楼上的用过recyclerview没,该listview是强制使用的viewholder的。他卡顿不是网络任务多,就是图片多。
顶一下 ~~~! 顶一下 ~~~! 顶一下 ~~~!
17839关注|2046收录
其他相似问题4980人阅读
Android技术笔记(64)
RecyclerView使用 及 滑动时加载图片优化方案简述 本篇博文主要给大家分享关于RecyclerView控件的使用及通过继承RecyclerView来实现滑动时加载图片的优化方案,也同样能解决防止图片乱序的问题,之前有在网上有看到大神对Android中ListView异步加载图片乱序问题进行过分析,并深入剖析原理后分别给出了3种对应的解决方案:一 、使用findViewWithTag。二、使用弱引用关联。三、使用Volley框架提供的NetworkImageView。看了之后思索了很久,后来才想到,哦,原来自己也一直这么在用。也算是一种解决方案吧,虽然不是从问题的根本进行处理,但根据实际业务需要,也同样能合理的解决。如以下两种方案:1、控制线程数量 + 数据分页加载2、重写onScrollStateChanged方法这个我们后面再谈,下面先来看看RecyclerView控件的使用及我们为什么选择使用它。RecyclerView的使用 RecyclerView 位于package android.support.v7. 包下,直接继承了android.view.ViewGroup,是Android中新添加的一个用来取代ListView的滑动控件,其灵活性与可替代性比ListView更优秀,运行原理与ListView类似,都是通过维护少量的View可展示大量的数据集。总结其优点:一、标准化了ViewHolder,使用Adapter适配器时,面向ViewHolder而不是单纯的View,直接把ViewHolder的实现封装起来,用户只要实现自己的ViewHolder就可以了,该组件会自动帮你回收并复用每一个item。不但变得更精简,也变得更加容易使用,而且更容易组合设计出自己需要的滑动布局。二、将Layout抽象成了一个LayoutManager,RecyclerView不负责子View的布局,而是通过使用LayoutManager来实现不同的布局效果,如使用LinearLayoutManager来指定方向,其默认是垂直,也可以设置为水平,当然你也可以自己来定义。我们来看看官方给出的示例:1.MyActivity.java
public class MyActivity extends Activity {
private RecyclerView mRecyclerV
private RecyclerView.Adapter mA
private RecyclerView.LayoutManager mLayoutM
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// improve performance if you know that changes in content do not change the size of the RecyclerView
//如果确定每个item的内容不会改变RecyclerView的大小,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
//创建默认的线性LayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
//设置Adapter
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。提供默认的动画效果,你也可以定义你自己的LayoutManager和添加删除动画。在回收或重用一个View时,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法。2.MyAdapter
public class MyAdapter extends RecyclerView.Adapter&MyAdapter.ViewHolder& {
private String[] mD
// Provide a reference to the type of views that you are using (custom viewholder)
//自定义的ViewHolder,持有每个Item的的所有界面元素
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextV
public ViewHolder(TextView v) {
mTextView =
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myD
// Create new views (invoked by the layout manager)
//创建新View,被LayoutManager调用
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
// Replace the contents of a view (invoked by the layout manager)
//将数据与界面进行绑定
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);
// Return the size of your dataset (invoked by the layout manager)
//这个就不解释了
public int getItemCount() {
return mDataset.
}Adapter:在使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。3.XML布局&!-- A RecyclerView with some commonly used attributes --&
&android.support.v7.widget.RecyclerView
android:id=&@+id/my_recycler_view&
android:scrollbars=&vertical&
android:layout_width=&match_parent&
android:layout_height=&match_parent&/&注:recyclerview N skipping layout&若出现该错误,是由于跳过了布局,没有Adapter与之对接的原因。附:①设置为横向的List:mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);②设置Grid布局列表,声明LayoutManager为GridLayoutManager即可:mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);③瀑布流布局//使用StaggeredGridLayoutManager从上述例子可以看出,RecyclerView的用法并不复杂,反而更灵活好用,它将数据、排列方式、数据的展示方式都分割开来,自定义的形式也非常多,非常灵活。下方共享一个开源示例,且解决了ScrollView嵌套RecyclerView无法显示的问题:& & & &&& & &下载链接:滑动时图片优化方案描述1、控制线程数量 + 数据分页加载我们在使用滑动控件呈现图片数据时,显然都会在getView方法里创建新的线程去异步加载图片,不可能有一百条或上千条数据一口气全部塞过来吧(当然你要这么干也是可以的),那么根据项目需求必然会进行分页加载,咱一页显示的item条数也别太夸张就好。而且,当我们点击屏幕快速向下滑动时,每个Item都会调用getView一次,必然会创建出很多线程去加载图片的URL资源,控制好线程的数量,加个线程池就非常有必要了。为了避免OOM导致FC,注意图片需要缓存,因为从内存中读取图片资源是非常快的。2、重写onScrollStateChanged方法这种方案用的也很普遍,相信只要细心观察,就会发现类似微博、Facebook、或者一些图片壁纸类的APP,在滑动时未加载的图片是不会立刻加载呈现的,只有当滑动停止后才会加载,这里需要注意一点的是,只加载当前屏幕内的图片。这么一说可能有童鞋就明白了。我们可以通过继承RecyclerView去自定义一个滑动控件,通过继承OnScrollListener后重写其 onScrolled方法 和&onScrollStateChanged 等方法来做相应处理。例如:private class AutoLoadScrollListener extends OnScrollListener {
public void onScrollStateChanged(RecyclerView recyclerView, int newState){
}我们通过 extends&OnScrollListener 并且&@Override 其&onScrollStateChanged 方法,通过判断state来处理,此处对其滚动的状态newState做一个说明,方面大家了解学习,分别有3个状态,即 0 - 1 - 2:状态为0时:当前屏幕停止滚动;状态为1时:屏幕在滚动 且 用户仍在触碰或手指还在屏幕上;状态为2时:随用户的操作,屏幕上产生的惯性滑动;实现我们就不自己去写那些异步加载图片,缓存啥的代码块了,简单明了,直接使用ImageLoader就可以。下面通过实例讲解该功能的实现,老规矩,先来效果图:& & & & & & &&先来瞄瞄activity_main.xml布局文件:&?xml version=&1.0& encoding=&utf-8&?&
&LinearLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:fitsSystemWindows=&true&
android:orientation=&vertical&&
&RelativeLayout
android:id=&@+id/layout_titlebar&
android:layout_width=&match_parent&
android:layout_height=&48dp&
android:background=&#00F1A0&&
android:textSize=&16dp&
android:id=&@+id/text_title&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:gravity=&center&
android:text=&好慌~&
android:textColor=&@android:color/white& /&
&/RelativeLayout&
&FrameLayout
android:id=&@+id/frame_container&
android:layout_width=&match_parent&
android:layout_height=&match_parent& /&
&/LinearLayout&很简单,用了一个Fragment而已,再来看看主Fragment的布局:&?xml version=&1.0& encoding=&utf-8&?&
&FrameLayout xmlns:android=&/apk/res/android&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:background=&@android:color/white&&
&android.support.v4.widget.SwipeRefreshLayout
android:id=&@+id/swipeRefreshLayout&
android:layout_width=&match_parent&
android:layout_height=&match_parent&&
&org.gaochun.view.AutoLoadRecyclerView
android:id=&@+id/recycler_view&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:scrollbars=&vertical& /&
&/android.support.v4.widget.SwipeRefreshLayout&
&/FrameLayout& 我们使用了&SwipeRefreshLayout 中包裹了自定义的&AutoLoadRecyclerView,关于SwipeRefreshLayout 控件的使用,大家可以自行百度,这里就不多说了。有盆友可能会说,挖槽,好慌~ ,这测试图哪来的,貌似还挺清晰的哇,好吧,只能帮你到这了:package org.gaochun.
import java.util.ArrayL
import java.util.L
* Created by gao_chun on .
public class ImageUrl {
public static List&String& imageList(){
List&String& mUrls = new ArrayList&String&();
mUrls.add(&http://e./image/pic/item/a1ec08fa513d57fbb2fb4316d81e.jpg&);
mUrls.add(&http://c./image/pic/item/30adcbefa2fe5a1cc7cd98d109d99.jpg&);
mUrls.add(&http://h./image/pic/item/7c1ed21b0ef41bd5f2c2a9e953da81cb39db3d1d.jpg&);
mUrls.add(&http://g./image/pic/item/55e736d12f2eb938df4a.jpg&);
mUrls.add(&http://e./image/pic/item/4e4a20ae41f5cfe760e0cf3d6cad6ee.jpg&);
mUrls.add(&http://b./image/pic/item/9d82d158ccbf6c81b94575cfb93eb1.jpg&);
mUrls.add(&http://e./image/pic/item/4bed2e738bd4b31c1badd5a685dff81e.jpg&);
mUrls.add(&/uploadfile/854.jpg&);
mUrls.add(&/uploadfile/989.jpg&);
mUrls.add(&http://g./image/pic/item/0d338744ebf81a4c87a3add4d52ae.jpg&);
mUrls.add(&http://a./image/pic/item/f2deb48f8ccfe99257e19.jpg&);
mUrls.add(&http://f./image/pic/item/e251fa586cf9.jpg&);
mUrls.add(&http://b./image/pic/item/d6d55fbbf4a20a4dd7e.jpg&);
mUrls.add(&/bbs/hfhouse/data/attachment/forum/corebbs/6298.jpg&);
mUrls.add(&http://a./image/pic/item/e824b899a87af4f464.jpg&);
mUrls.add(&http://c./image/pic/item/9c16fdfaaf51f3de1e296fa390eef01f3b29795a.jpg&);
mUrls.add(&http://d./image/pic/item/b58f8c5494eef01f119945cbe2fea.jpg&);
mUrls.add(&http://h./image/pic/item/902397dda144add4a20cf430ad851e.jpg&);
mUrls.add(&http://b./image/pic/item/359b033b5bb5c9ea5c0e3c23d139b.jpg&);
mUrls.add(&http://a./image/pic/item/8d5494eef01f3a292dbc315d607c7c.jpg&);
mUrls.add(&http://b./image/pic/item/e824b899ab2c4c0e7b0a3.jpg&);
mUrls.add(&http://g./image/pic/item/6dbc3e770bd00d868ba61ea9d345f2.jpg&);
下面来看看主要的类AutoLoadRecyclerView,其实这个类也很简单:public class AutoLoadRecyclerView extends RecyclerView implements LoadFinishCallBack {
private onLoadMoreListener loadMoreL //加载更多回调
private boolean isLoadingM
//是否加载更多
public AutoLoadRecyclerView(Context context) {
this(context, null);
public AutoLoadRecyclerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public AutoLoadRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
isLoadingMore = //默认无需加载更多
setOnScrollListener(new AutoLoadScrollListener(null, true, true));
* 配置显示图片,需要设置这几个参数,快速滑动时,暂停图片加载
* @param imageLoader ImageLoader实例对象
* @param pauseOnScroll
* @param pauseOnFling
public void setOnPauseListenerParams(ImageLoader imageLoader, boolean pauseOnScroll, boolean pauseOnFling) {
setOnScrollListener(new AutoLoadScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
public void setLoadMoreListener(onLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreL
public void loadFinish(Object obj) {
isLoadingMore =
//加载更多的回调接口
public interface onLoadMoreListener {
void loadMore();
* 滑动自动加载监听器
private class AutoLoadScrollListener extends OnScrollListener {
private ImageLoader imageL
private final boolean pauseOnS
private final boolean pauseOnF
public AutoLoadScrollListener(ImageLoader imageLoader, boolean pauseOnScroll, boolean pauseOnFling) {
this.pauseOnScroll = pauseOnS
this.pauseOnFling = pauseOnF
this.imageLoader = imageL
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//由于GridLayoutManager是LinearLayoutManager子类,所以也适用
if (getLayoutManager() instanceof LinearLayoutManager) {
int lastVisibleItem = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
int totalItemCount = AutoLoadRecyclerView.this.getAdapter().getItemCount();
//有回调接口,且不是加载状态,且计算后剩下2个item,且处于向下滑动,则自动加载
if (loadMoreListener != null && !isLoadingMore && lastVisibleItem &= totalItemCount -
2 && dy & 0) {
loadMoreListener.loadMore();
isLoadingMore =
//当屏幕停止滚动时为0;当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1;由于用户的操作,屏幕产生惯性滑动时为2
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
//根据newState状态做处理
if (imageLoader != null) {
switch (newState) {
imageLoader.resume();
if (pauseOnScroll) {
imageLoader.pause();
imageLoader.resume();
if (pauseOnFling) {
imageLoader.pause();
imageLoader.resume();
}也就是说,我们通过定义了一个&setOnPauseListenerParams&方法去设置滑动监听事件setOnScrollListener,并通过定义内部类AutoLoadScrollListener去@Override相关方法并做相应的处理。下载链接:【转载注明gao_chun的Blog:http://blog.csdn.net/gao_chun/article/details/】
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:872680次
积分:13179
积分:13179
排名:第648名
原创:242篇
转载:46篇
评论:535条
文章:24篇
阅读:78142
阅读:40277
文章:18篇
阅读:59174
文章:46篇
阅读:169923
文章:18篇
阅读:78618
文章:34篇
阅读:123823

我要回帖

更多关于 recyclerview横向滑动 的文章

 

随机推荐