android recyclerview滑动监听滑过多少条
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android recyclerview滑动监听滑过多少条相关的知识,希望对你有一定的参考价值。
参考技术A 1.利用OnScrollListener[java]viewplaincopymRecyclerView.addOnScrollListener(newRecyclerView.OnScrollListener()privateinttotalDy=0;@OverridepublicvoidonScrolled(RecyclerViewrecyclerView,intdx,intdy)totalDy-=dy;);如代码所述,totalDy的确保存了RecyclerView的滑动距离,但是当我向下滑动RecyclerView,之后插入/删除/移动Item的时候,totalDy就变得不精确了;比如删除或者插入新的Item,那么totalDy就不能再回归到0了。解决法:监听RecyclerView的addOnScrollListener后自己记录onScrolled的dy,同时给adapter加个registerAdapterDataObserver,监听插入/删除/移动,自己加减前面记录的dy滚动值。自己没有试过,不知道是否可行!2.有人说可以尝试computeVerticalScrollOffset()[java]viewplaincopytotalDy=recyclerView.computeVerticalScrollOffset();然而compute方法计算出的并不是滑动的精确距离,stackOverflow上有答案解释其为item的平均高度*可见item数目,不是我们需要的精确距离。3.还有人说可以尝试getChildAt(0)[java]viewplaincopytotalDy=recyclerView.getChildAt(0).getTop();依靠第一个item的滑动距离来进行动画的设置,但是根据该方法得出的totalDy在滑动到一定程度后清零。这是因为recyclerViewl.getChildAt(0)返回的永远是第一个可见的child,不是所有viewlist的第一个child,因此这种用法是得不到滑动距离的。另外下面这三种用法都是等价的,都是获取第一个可见的child:[java]viewplaincopyLinearLayoutManagerlayoutManager=(LinearLayoutManager)this.getLayoutManager();ViewfirstVisiableChildView=this.getChildAt(0);ViewfirstVisiableChildView=layoutManager.getChildAt(0)intposition=layoutManager.findFirstVisibleItemPosition();ViewfirstVisiableChildView=layoutManager.getChildAt(position)但是下面这种就不是获取第一个可见的child,而是获得所有viewlist的第一个child。但是滑动一段距离后它总是返回null,即第一个child被recycle后,总是返回null。[java]viewplaincopy//Don'tusethisfunctiontogetthefirstitem,itwillreturnnullwhenthefirstitemisrecycled.LinearLayoutManagerlayoutManager=(LinearLayoutManager)this.getLayoutManager();Viewchild2=layoutManager.findViewByPosition(0);4.如果LayoutManager用的是LinearLayoutManager,强烈推荐下面的方法获取滑动距离:[java]viewplaincopypublicintgetScollYDistance()LinearLayoutManagerlayoutManager=(LinearLayoutManager)this.getLayoutManager();intposition=layoutManager.findFirstVisibleItemPosition();ViewfirstVisiableChildView=layoutManager.findViewByPosition(position);intitemHeight=firstVisiableChildView.getHeight();return(position)*itemHeight-firstVisiableChildView.getTop();本回答被提问者采纳Android之RecyclerView轻松实现下拉刷新和加载更多
今天研究了下RecyclerView的滑动事件,特别是下拉刷新和加载更多事件,在现在几乎所有的APP显示数据列表时都用到了。自定义RecyclerView下拉刷新和加载更多听上去很复杂,实际上并不难,只要是对滑动事件的监听和处理。
一、自定义RecyclerView实现下拉刷新和加载更多
1、如何判断RecyclerView是在上滑还是下滑
在RecyclerView的OnScrollListener滑动事件监听中有个好用的方法,就是onScrolled(RecyclerView recyclerView, int dx, int dy),其中根据dx的值的正负就可以判断是在左滑还是右滑,而根据dy的值就可以判断是在上滑还是下滑。
1 //上滑 2 if(dy>0){ 3 //相应操作代码 4 } 5 //下滑 6 else if(dy<0){ 7 //相应操作代码 8 }
2、如何判断是否滑到了顶部或者底部
同样在RecyclerView的OnScrollListener滑动事件监听中onScrolled(RecyclerView recyclerView, int dx, int dy)方法中处理,根据canScrollVertically(int direction)来进行判断。
1 //是否滑到底部 2 if(!recyclerView.canScrollVertically(1)){ 3 //相应处理操作 4 } 5 //是否滑到顶部 6 if(!recyclerView.canScrollVertically(-1)){ 7 //相应处理操作 8 }
3、自定义RecyclerView
知道了滑动事件的判断和处理,就可以很轻松得实现下拉刷新和加载更多了。
1 import android.content.Context; 2 import android.support.annotation.Nullable; 3 import android.support.v7.widget.RecyclerView; 4 import android.util.AttributeSet; 5 import android.util.Log; 6 7 /** 8 * Package:com.liuting.library 9 * author:liuting 10 * Date:2017/2/14 11 * Desc:自定义RecycleView,下拉刷新以及上拉加载更多 12 */ 13 14 public class RefreshLoadMoreRecycleView extends RecyclerView { 15 private Boolean isLoadMore;//是否可以加载更多标志 16 private Boolean isLoadEnd;//加载到最后的标志 17 private Boolean isLoadStart;//顶部的标志 18 private Boolean isRefresh;//是否可以下拉刷新标志 19 private int lastVisibleItem;//最后一项 20 private IOnScrollListener listener;//事件监听 21 22 public RefreshLoadMoreRecycleView(Context context) { 23 super(context); 24 init(context); 25 } 26 27 public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs) { 28 super(context, attrs); 29 init(context); 30 } 31 32 public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { 33 super(context, attrs, defStyle); 34 init(context); 35 } 36 37 public void init(Context context) { 38 isLoadEnd=false; 39 isLoadStart =true; 40 41 this.addOnScrollListener(new RecyclerView.OnScrollListener() { 42 @Override 43 public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 44 super.onScrollStateChanged(recyclerView, newState); 45 //SCROLL_STATE_DRAGGING 和 SCROLL_STATE_IDLE 两种效果自己看着来 46 if (newState == RecyclerView.SCROLL_STATE_IDLE) { 47 if (isLoadEnd) { 48 // 判断是否已加载所有数据 49 if (isLoadMore) {//未加载完所有数据,加载数据,并且还原isLoadEnd值为false,重新定位列表底部 50 if (getListener() != null) { 51 getListener().onLoadMore(); 52 } 53 } else {//加载完了所有的数据 54 if(getListener()!=null){ 55 getListener().onLoaded(); 56 } 57 } 58 isLoadEnd = false; 59 } else if (isLoadStart) { 60 if(isRefresh){ 61 if (getListener() != null) { 62 getListener().onRefresh(); 63 } 64 isLoadStart=false; 65 } 66 } 67 68 } 69 } 70 71 @Override 72 public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 73 super.onScrolled(recyclerView, dx, dy); 74 //上滑 75 if(dy>0){ 76 //是否滑到底部 77 if(!recyclerView.canScrollVertically(1)){ 78 isLoadEnd = true; 79 }else{ 80 isLoadEnd = false; 81 } 82 } 83 //下滑 84 else if(dy<0){ 85 //是否滑到顶部 86 if(!recyclerView.canScrollVertically(-1)){ 87 isLoadStart=true; 88 }else{ 89 isLoadStart=false; 90 } 91 } 92 } 93 }); 94 } 95 96 //监听事件 97 public interface IOnScrollListener { 98 void onRefresh(); 99 100 void onLoadMore(); 101 102 void onLoaded(); 103 } 104 105 public IOnScrollListener getListener() { 106 return listener; 107 } 108 109 public void setListener(IOnScrollListener listener) { 110 this.listener = listener; 111 } 112 113 public Boolean getLoadMore() { 114 return isLoadMore; 115 } 116 117 //设置是否支持加载更多 118 public void setLoadMoreEnable(Boolean loadMore) { 119 isLoadMore = loadMore; 120 } 121 122 public Boolean getRefresh() { 123 return isRefresh; 124 } 125 126 //设置是否支持下拉刷新 127 public void setRefreshEnable(Boolean refresh) { 128 isRefresh = refresh; 129 } 130 }
二、实际用例
已经定义好了RecyclerView,下面在Demo中实际使用和处理。
1、定义布局
布局文件很简单,就是一个RecyclerView
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:id="@+id/activity_main" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 android:orientation="vertical" 9 tools:context="com.liuting.refreshloadmorelistview.MainActivity"> 10 11 <com.liuting.library.RefreshLoadMoreRecycleView 12 android:id="@+id/main_recycle_view_data" 13 android:layout_width="match_parent" 14 android:layout_height="match_parent" 15 android:scrollbars="none" 16 /> 17 </LinearLayout>
2、定义RecyclerView.Adapter
RecyclerView.Adapter在这里就简单处理了,列表布局直接使用Android自带的。
1 import android.content.Context; 2 import android.support.v7.widget.RecyclerView; 3 import android.view.LayoutInflater; 4 import android.view.View; 5 import android.view.ViewGroup; 6 import android.widget.TextView; 7 8 import java.util.List; 9 10 /** 11 * Package:com.liuting.refreshloadmorelistview.adapter 12 * author:liuting 13 * Date:2017/2/16 14 * Desc:列表Adapter 15 */ 16 17 public class RefreshLoadMoreRecycleAdapter extends RecyclerView.Adapter<RefreshLoadMoreRecycleAdapter.ViewHolder> { 18 private List<String> list; 19 private Context context; 20 21 public RefreshLoadMoreRecycleAdapter(Context context,List<String> list) { 22 this.context =context; 23 this.list = list; 24 } 25 26 @Override 27 public RefreshLoadMoreRecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 28 View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_expandable_list_item_1, parent, false); 29 RefreshLoadMoreRecycleAdapter.ViewHolder viewHolder = new RefreshLoadMoreRecycleAdapter.ViewHolder(view); 30 return viewHolder; 31 } 32 33 @Override 34 public void onBindViewHolder(ViewHolder holder, int position) { 35 holder.text.setText(list.get(position)); 36 holder.itemView.setTag(position); 37 } 38 39 @Override 40 public int getItemCount() { 41 return list.size(); 42 } 43 44 class ViewHolder extends RecyclerView.ViewHolder{ 45 private TextView text; 46 47 public ViewHolder(View itemView) { 48 super(itemView); 49 text=(TextView)itemView.findViewById(android.R.id.text1); 50 } 51 } 52 }
3、在Activity中定义好控件以及数据加载操作
实现自定义RecyclerView中的数据加载事件监听,刷新、加载更多以及加载完成。
1 import android.app.ProgressDialog; 2 import android.os.Bundle; 3 import android.os.Handler; 4 import android.os.Message; 5 import android.support.v7.app.AppCompatActivity; 6 import android.support.v7.widget.LinearLayoutManager; 7 import android.widget.Toast; 8 9 import com.liuting.library.RefreshLoadMoreRecycleView; 10 import com.liuting.refreshloadmorelistview.adapter.RefreshLoadMoreRecycleAdapter; 11 12 import java.util.ArrayList; 13 import java.util.List; 14 15 public class MainActivity extends AppCompatActivity implements RefreshLoadMoreRecycleView.IOnScrollListener{ 16 private RefreshLoadMoreRecycleView recycleView;//下拉刷新RecycleView 17 private List<String> list;//列表 18 private RefreshLoadMoreRecycleAdapter adapter;//Adapter 19 private ProgressDialog dialog;//提示框 20 private static final int REFRESH_Load=0;//下拉刷新 21 private static final int MORE_Load=1;//加载更多 22 private Handler handler =new Handler(){ 23 @Override 24 public void handleMessage(Message msg) { 25 super.handleMessage(msg); 26 switch (msg.what){ 27 case REFRESH_Load: 28 recycleView.setLoadMoreEnable(true); 29 dismissDialog(); 30 if(list!=null){ 31 list.clear(); 32 } 33 loadData(); 34 adapter.notifyDataSetChanged(); 35 break; 36 case MORE_Load: 37 recycleView.setLoadMoreEnable(false); 38 dismissDialog(); 39 loadData(); 40 adapter.notifyDataSetChanged(); 41 break; 42 } 43 } 44 }; 45 46 @Override 47 protected void onCreate(Bundle savedInstanceState) { 48 super.onCreate(savedInstanceState); 49 setContentView(R.layout.activity_main); 50 initView(); 51 } 52 53 public void initView(){ 54 dialog = new ProgressDialog(MainActivity.this); 55 56 list=new ArrayList<>(); 57 loadData(); 58 recycleView = (RefreshLoadMoreRecycleView)findViewById(R.id.main_recycle_view_data); 59 60 final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity.this); 61 recycleView.setLayoutManager(linearLayoutManager); 63 adapter = new RefreshLoadMoreRecycleAdapter(MainActivity.this,list); 64 recycleView.setAdapter(adapter); 65 recycleView.setListener(this); 66 recycleView.setRefreshEnable(true); 67 recycleView.setLoadMoreEnable(true); 68 } 69 70 /** 71 * 加载数据 72 */ 73 public void loadData(){ 74 for(int i=0;i<10;i++ ){ 75 list.add("It is "+i); 76 } 77 } 78 79 @Override 80 public void onRefresh() { 81 showDialog(); 82 new Thread(){ 83 @Override 84 public void run() { 85 super.run(); 86 try { 87 sleep(5000); 88 handler.sendEmptyMessage(REFRESH_Load); 89 } catch (InterruptedException e) { 90 e.printStackTrace(); 91 } 92 } 93 }.start(); 94 } 95 96 @Override 97 public void onLoadMore() { 98 showDialog(); 99 new Thread(){ 100 @Override 101 public void run() { 102 super.run(); 103 try { 104 sleep(5000); 105 handler.sendEmptyMessage(MORE_Load); 106 } catch (InterruptedException e) { 107 e.printStackTrace(); 108 } 109 } 110 }.start(); 111 } 112 113 @Override 114 public void onLoaded() { 115 Toast.makeText(MainActivity.this,"Loaded all",Toast.LENGTH_SHORT).show(); 116 } 117 118 /** 119 * dismiss dialog 120 */ 121 private void dismissDialog(){ 122 if (dialog!=null&&dialog.isShowing()){ 123 dialog.dismiss(); 124 } 125 } 126 127 /** 128 * show dialog 129 */ 130 private void showDialog(){ 131 if (dialog!=null&&!dialog.isShowing()){ 132 dialog.show(); 133 } 134 } 135 }
三、最终效果图
到这里就轻松实现了RecyclerView的下拉刷新和加载更多了。
以上是关于android recyclerview滑动监听滑过多少条的主要内容,如果未能解决你的问题,请参考以下文章
Android Recyclerview 监听滑动状态和滑动距离
Android Recyclerview 监听滑动状态和滑动距离
Android——实现RecyclerView左侧滑删除与右侧滑选择