RecyclerView实现下拉刷新和加载更多

2023-01-02  本文已影响0人  古早味蛋糕
一、介绍

RecyclerView的滑动事件,特别是下拉刷新和加载更多事件,现在几乎所有的APP显示数据列表时都会用到。今天在此记录一下自定义RecyclerView下拉刷新和加载更多的实现,主要是对滑动事件的监听和处理。

二、RecyclerView实现下拉刷新和加载更多
1、RecyclerView的滑动监听事件,监听上下滑动作

在RecyclerView的OnScrollListener滑动事件监听中有个好用的方法,就是onScrolled(RecyclerView recyclerView, int dx, int dy),其中根据dx的值的正负就可以判断是在左滑还是右滑,而根据dy的值就可以判断是在上滑还是下滑。

//上滑
 if(dy>0){
 //相应操作代码

 }
 //下滑
 else if(dy<0){
 //相应操作代码

 }
2、判断是否滑到了列表的顶部或者列表底部
 //是否滑到底部
  if(!recyclerView.canScrollVertically(1)){
      //相应处理操作

  }

  //是否滑到顶部
  if(!recyclerView.canScrollVertically(-1)){
      //相应处理操作

  }
3、在RecyclerView实现自定义

知道了滑动事件的判断和处理,就可以很轻松得实现下拉刷新和加载更多了。

public class RefreshRecycleView extends RecyclerView implements RecyclerView.OnTouchListener {
    private Boolean isLoadMore;//加载更多标志

    private Boolean isLoadEnd;//加载到最后的标志

    private Boolean isLoadStart;//顶部的标志

    private Boolean isRefresh;//下拉刷新标志

    private IOnScrollListener listener;//事件监听

    private float mLastY;//监听移动的位置

    public RefreshRecycleView(Context context) {
        this(context,null);
    }

    public RefreshRecycleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);

    }

    public RefreshRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();

    }

    /**
     * 初始化
     */
    public void init() {

        isLoadEnd = false;

        isLoadStart = true;

        this.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override

            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //SCROLL_STATE_DRAGGING 拖动时  和   SCROLL_STATE_IDLE 当屏幕停止滚动时
                // SCROLL_STATE_SETTLING 要移动到最后位置时

                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    loadData();
                }

            }

            @Override

            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                //上滑
                if (dy > 0) {

                    //是否滑到底部
                    if (!recyclerView.canScrollVertically(1)) {
                        isLoadEnd = true;
                    } else {
                        isLoadEnd = false;
                    }

                } else if (dy < 0) {

                    //是否滑到顶部
                    if (!recyclerView.canScrollVertically(-1)) {
                        isLoadStart = true;
                    } else {
                        isLoadStart = false;
                    }

                }

            }

        });

        this.setOnTouchListener(this);

    }

    /**
     * 加载数据
     */

    private void loadData() {

        if (isLoadEnd) {
            // 判断是否已加载所有数据
            if (isLoadMore) {//未加载完所有数据,加载数据,并且还原isLoadEnd值为false,重新定位列表底部

                if (getListener() != null) {
                    getListener().onLoadMore();
                }

            } else {//加载完了所有的数据
                if (getListener() != null) {
                    getListener().onLoaded();
                }

            }
            isLoadEnd = false;

        } else if (isLoadStart) {

            if (isRefresh) {
                if (getListener() != null) {
                    getListener().onRefresh();
                }

                isLoadStart = false;

            }

        }

    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {

        if (mLastY == -1) {
            mLastY = motionEvent.getRawY();
        }

        switch (motionEvent.getAction()) {

            case MotionEvent.ACTION_MOVE:

                final float deltaY = motionEvent.getRawY() - mLastY;

                mLastY = motionEvent.getRawY();

                //向上移动
                if (deltaY < 0) {

                    //是否滑到底部
                    if (!this.canScrollVertically(1)) {

                        isLoadEnd = true;

                    } else {

                        isLoadEnd = false;

                    }

                }

                //向下移动
                else if (deltaY > 0) {

                    //是否滑到顶部
                    if (!this.canScrollVertically(-1)) {

                        isLoadStart = true;

                    } else {

                        isLoadStart = false;

                    }

                }

                break;

            case MotionEvent.ACTION_DOWN:

                mLastY = motionEvent.getRawY();

                break;

            default://重置

                mLastY = -1;

                break;

        }

        return false;

    }

    //事件监听
    public interface IOnScrollListener {

        void onRefresh();

        void onLoadMore();

        void onLoaded();

    }

    public IOnScrollListener getListener() {

        return listener;

    }

    //设置事件监听

    public void setListener(IOnScrollListener listener) {

        this.listener = listener;

    }

    public Boolean getLoadMore() {

        return isLoadMore;

    }

    //设置是否支持加载更多

    public void setLoadMoreEnable(Boolean loadMore) {

        isLoadMore = loadMore;

    }

    public Boolean getRefresh() {

        return isRefresh;

    }

    //设置是否支持下拉刷新
    public void setRefreshEnable(Boolean refresh) {

        isRefresh = refresh;

    }

}
三、使用RefreshRecycleView实现刷新功能
1、定义布局

引用自定义的RefreshRecycleView就可以
activity_refresh.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RefreshActivity">
    <com.zyd.screenautosize.RefreshRecycleView
        android:id="@+id/main_recycle_view_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2、定义RecyclerView.Adapter

这里只是用系统自带的item布局

public class RefreshRecycleAdapter extends RecyclerView.Adapter<RefreshRecycleAdapter.ViewHolder> {

    private List<String> list;

    private Context context;

    public RefreshRecycleAdapter(Context context, List<String> list) {

        this.context = context;
        this.list = list;

    }

    @Override

    public RefreshRecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_expandable_list_item_1, parent, false);

        RefreshRecycleAdapter.ViewHolder viewHolder = new RefreshRecycleAdapter.ViewHolder(view);

        return viewHolder;

    }

    @Override

    public void onBindViewHolder(ViewHolder holder, int position) {

        holder.text.setText(list.get(position));

        holder.itemView.setTag(position);

    }

    @Override

    public int getItemCount() {

        return list.size();

    }

    class ViewHolder extends RecyclerView.ViewHolder {

        private TextView text;

        public ViewHolder(View itemView) {

            super(itemView);

            text = itemView.findViewById(android.R.id.text1);

        }

    }

}   
3、在Activity中初始化控件以及数据加载
public class RefreshActivity extends AppCompatActivity implements RefreshRecycleView.IOnScrollListener {

    private RefreshRecycleView recycleView;//下拉刷新RecycleView

    private List<String> list;//列表

    private RefreshRecycleAdapter adapter;//Adapter

    private AlertDialog.Builder builder;//提示框
    private Dialog dialogProgress;

    private static final int REFRESH_Load = 0;//下拉刷新

    private static final int MORE_Load = 1;//加载更多

    private Handler handler = new Handler(Looper.myLooper()) {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case REFRESH_Load:

                    recycleView.setLoadMoreEnable(true);

                    if (dialogProgress.isShowing()) {
                        dialogProgress.hide();
                    }

                    if (list != null) {
                        list.clear();
                    }

                    loadData();

                    adapter.notifyDataSetChanged();

                    break;

                case MORE_Load:

                    recycleView.setLoadMoreEnable(false);

                    if (dialogProgress.isShowing()) {
                        dialogProgress.hide();
                    }

                    loadData();

                    adapter.notifyDataSetChanged();

                    break;

            }

        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_refresh);
        initView();
    }

    public void initView() {

        builder = new AlertDialog.Builder(this);
        setDialog(false);

        list = new ArrayList<>();

        loadData();

        recycleView = findViewById(R.id.main_recycle_view_data);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(RefreshActivity.this);

        recycleView.setLayoutManager(linearLayoutManager);

        adapter = new RefreshRecycleAdapter(RefreshActivity.this, list);

        recycleView.setAdapter(adapter);

        recycleView.setListener(this);

        recycleView.setRefreshEnable(true);

        recycleView.setLoadMoreEnable(true);

    }

    /**
     * 设置Dialog
     * @param isShow
     */
    private void setDialog(boolean isShow) {
        builder.setView(R.layout.layout_progress);
        dialogProgress = builder.create();
        dialogProgress.setCanceledOnTouchOutside(false);
        if (isShow) {
            dialogProgress.show();
        } else {
            dialogProgress.dismiss();
        }
    }

    /**
     * 加载数据
     */

    public void loadData() {

        for (int i = 0; i < 10; i++) {

            list.add("第" + i +"行");

        }

    }

    @Override
    public void onRefresh() {

        if (!dialogProgress.isShowing()) {
            dialogProgress.show();
        }

        new Thread() {

            @Override
            public void run() {
                super.run();

                try {

                    sleep(3000);

                    handler.sendEmptyMessage(REFRESH_Load);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }.start();

    }

    @Override
    public void onLoadMore() {

        if (!dialogProgress.isShowing()) {
            dialogProgress.show();
        }

        new Thread() {

            @Override
            public void run() {
                super.run();

                try {

                    sleep(3000);

                    handler.sendEmptyMessage(MORE_Load);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }.start();

    }

    @Override
    public void onLoaded() {

        Toast.makeText(RefreshActivity.this, "Loaded all", Toast.LENGTH_SHORT).show();

    }

}

4.效果图如下:


1.gif
上一篇下一篇

猜你喜欢

热点阅读