zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    451. Sort Characters By Frequency
    424. Longest Repeating Character Replacement
    68. Text Justification
    44. Wildcard Matching
    160. Intersection of Two Linked Lists
    24. Swap Nodes in Pairs
    93. 递归实现组合型枚举
    98. 分形之城
    97. 约数之和
    96. 奇怪的汉诺塔
  • 原文地址:https://www.cnblogs.com/LT5505/p/6409621.html
Copyright © 2011-2022 走看看