• 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 import android.view.MotionEvent;
      7 import android.view.View;
      8 
      9 /**
     10  * Package:com.liuting.library
     11  * author:liuting
     12  * Date:2017/2/14
     13  * Desc:自定义RecycleView,下拉刷新以及上拉加载更多
     14  */
     15 
     16 public class RefreshLoadMoreRecycleView extends RecyclerView implements RecyclerView.OnTouchListener{
     17     private Boolean isLoadMore;//加载更多标志
     18     private Boolean isLoadEnd;//加载到最后的标志
     19     private Boolean isLoadStart;//顶部的标志
     20     private Boolean isRefresh;//下拉刷新标志
     21     private int lastVisibleItem;//最后一项
     22     private IOnScrollListener listener;//事件监听
     23     private float mLastY;//监听移动的位置
     24 
     25     public RefreshLoadMoreRecycleView(Context context) {
     26         super(context);
     27         init(context);
     28     }
     29 
     30     public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs) {
     31         super(context, attrs);
     32         init(context);
     33     }
     34 
     35     public RefreshLoadMoreRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
     36         super(context, attrs, defStyle);
     37         init(context);
     38     }
     39 
     40      /**
     41      * 初始化
     42      * 
     43      * @param context
     44      */
     45     public void init(Context context) {
     46         isLoadEnd=false;
     47         isLoadStart =true;
     48 
     49         this.addOnScrollListener(new RecyclerView.OnScrollListener() {
     50             @Override
     51             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
     52                 super.onScrollStateChanged(recyclerView, newState);
     53                 //SCROLL_STATE_DRAGGING  和   SCROLL_STATE_IDLE 两种效果自己看着来
     54                 if (newState == RecyclerView.SCROLL_STATE_IDLE) {
     55                     loadData();
     56                 }
     57             }
     58 
     59             @Override
     60             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
     61                 super.onScrolled(recyclerView, dx, dy);
     62                 //上滑
     63                 if(dy>0){
     64                     //是否滑到底部
     65                     if(!recyclerView.canScrollVertically(1)){
     66                         isLoadEnd = true;
     67                     }else{
     68                         isLoadEnd = false;
     69                     }
     70                     Log.e("TAG","Running--->>isLoadEnd:"+isLoadEnd+dy);
     71                 }else if(dy<0){
     72                     //是否滑到顶部
     73                     if(!recyclerView.canScrollVertically(-1)){
     74                         isLoadStart=true;
     75                     }else{
     76                         isLoadStart=false;
     77                     }
     78 
     79                 }
     80             }
     81         });
     82         this.setOnTouchListener(this);
     83     }
     84 
     85      /**
     86      * 
     87      * 加载数据
     88      * 
     89      */
     90     private void loadData() {
     91         if (isLoadEnd) {
     92             // 判断是否已加载所有数据
     93             if (isLoadMore) {//未加载完所有数据,加载数据,并且还原isLoadEnd值为false,重新定位列表底部
     94                 if (getListener() != null) {
     95                     getListener().onLoadMore();
     96                 }
     97             } else {//加载完了所有的数据
     98                 if(getListener()!=null){
     99                     getListener().onLoaded();
    100                 }
    101             }
    102             isLoadEnd = false;
    103         } else if (isLoadStart) {
    104             if(isRefresh){
    105                 if (getListener() != null) {
    106                     getListener().onRefresh();
    107                 }
    108                 isLoadStart=false;
    109             }
    110         }
    111     }
    112 
    113     @Override
    114     public boolean onTouch(View view, MotionEvent motionEvent) {
    115         if (mLastY == -1) {
    116             mLastY = motionEvent.getRawY();
    117         }
    118         switch (motionEvent.getAction()){
    119             case MotionEvent.ACTION_MOVE:
    120                 final float deltaY = motionEvent.getRawY() - mLastY;
    121                 mLastY = motionEvent.getRawY();
    122                 //向上移动
    123                 if(deltaY<0){
    124                     //是否滑到底部
    125                     if(!this.canScrollVertically(1)){
    126                         isLoadEnd = true;
    127                     }else{
    128                         isLoadEnd = false;
    129                     }
    130                 }
    131                 //向下移动
    132                 else if(deltaY>0) {
    133                     //是否滑到顶部
    134                     if (!this.canScrollVertically(-1)) {
    135                         isLoadStart = true;
    136                     } else {
    137                         isLoadStart = false;
    138                     }
    139                 }
    140                 break;
    141             case MotionEvent.ACTION_DOWN:
    142                 mLastY = motionEvent.getRawY();
    143                 break;
    144             default://重置
    145                 mLastY = -1;
    146                 break;
    147         }
    148 
    149         return false;
    150     }
    151 
    152     //事件监听
    153     public interface IOnScrollListener {
    154         void onRefresh();
    155 
    156         void onLoadMore();
    157 
    158         void onLoaded();
    159     }
    160 
    161     public IOnScrollListener getListener() {
    162         return listener;
    163     }
    164 
    165     //设置事件监听
    166     public void setListener(IOnScrollListener listener) {
    167         this.listener = listener;
    168     }
    169 
    170     public Boolean getLoadMore() {
    171         return isLoadMore;
    172     }
    173 
    174     //设置是否支持加载更多
    175     public void setLoadMoreEnable(Boolean loadMore) {
    176         isLoadMore = loadMore;
    177     }
    178 
    179     public Boolean getRefresh() {
    180         return isRefresh;
    181     }
    182 
    183     //设置是否支持下拉刷新
    184     public void setRefreshEnable(Boolean refresh) {
    185         isRefresh = refresh;
    186     }
    187 }

    二、实际用例

    已经定义好了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的下拉刷新和加载更多了。

    源代码放在了Github上:https://github.com/LT5505/RefreshLoadMoreRecycleView

  • 相关阅读:
    第一个SpringBoot
    windows 安装 mysql 及部分命令
    别让猴子跳回背上
    windows环境下基于Anaconda安装Tensorflow
    spark
    ubuntu环境下安装chrome
    前言
    模型压缩(4)
    模型压缩(3)
    模型压缩(2)
  • 原文地址:https://www.cnblogs.com/LT5505/p/6409621.html
Copyright © 2020-2023  润新知