Android RecyclerView滑动到底部/上拉/上拉见底自动加载更多实现以及点击/长按事件处理

Android RecyclerView滑动到底部/上拉/上拉见底自动加载更多实现以及点击/长按事件处理


Android RecyclerView下拉加载更多有Android谷歌官方的实现,实现的方式是通过SwipeRefreshLayout把RecyclerView包裹起来,然后就可以通过SwipeRefreshLayout的回调接口实现下拉刷新功能。
Android上拉加载上拉刷新的实现没有官方统一策略,现在我给出一个实现好的工具类:
import android.support.v7.widget.RecyclerView;

/**
 * Created by fly on 2018/3/22.
 */

public class RecyclerViewUtil {
    private boolean enable = true;
    private RecyclerView mRecyclerView;
    private RecyclerViewLoadMoreListener mRecyclerViewLoadMoreListener;

    public RecyclerViewUtil(RecyclerView mRecyclerView) {
        this.mRecyclerView = mRecyclerView;
    }

    public void setRecyclerViewLoadMoreListener(RecyclerViewLoadMoreListener listener) {
        this.mRecyclerViewLoadMoreListener = listener;
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                if (newState == RecyclerView.SCROLL_STATE_IDLE && isBottom(mRecyclerView)) {
                    if (enable && mRecyclerViewLoadMoreListener != null) {
                        mRecyclerViewLoadMoreListener.onLoadMore();
                    }
                }
            }
        });
    }

    public void setLoadMoreEnable(boolean enable) {
        this.enable = enable;
    }

    private boolean isBottom(RecyclerView recyclerView) {
        if (recyclerView == null)
            return false;

        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
            return true;

        return false;
    }

    public interface RecyclerViewLoadMoreListener {
        public void onLoadMore();
    }
}


使用方式,构造一个RecyclerViewUtil,把RecyclerView传递进去,就可以使用了。如:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private RecyclerViewAdapter mAdapter;
    private ArrayList<String> data;

    private int START_POS = 0;
    private RecyclerViewUtil mRecyclerViewUtil;

    private Random random = new Random();

    private int MAX_COUNT = 20;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        data = new ArrayList<>();
        int count = random.nextInt(MAX_COUNT);
        for (int i = 0; i < count; i++) {
            data.add(String.valueOf(i));
        }

        START_POS = START_POS + count;

        setContentView(R.layout.activity_main);

        RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
        LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
        mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLinearLayoutManager);

        mAdapter = new RecyclerViewAdapter();
        mRecyclerView.setAdapter(mAdapter);

        mRecyclerViewUtil = new RecyclerViewUtil(mRecyclerView);
        mRecyclerViewUtil.setRecyclerViewLoadMoreListener(new RecyclerViewUtil.RecyclerViewLoadMoreListener() {
            @Override
            public void onLoadMore() {
                Toast.makeText(getApplicationContext(), "已经到底,加载更多...", Toast.LENGTH_SHORT).show();
                mRecyclerViewUtil.setLoadMoreEnable(false);

                load(START_POS, random.nextInt(MAX_COUNT));
            }
        });
    }

    private void load(int startPos, int count) {
        for (int i = 0; i < count; i++) {
            data.add(startPos + i + "");
        }

        mAdapter.notifyDataSetChanged();
        Toast.makeText(getApplicationContext(), "加载了" + count + " 条数据", Toast.LENGTH_SHORT).show();

        START_POS = startPos + count;
        mRecyclerViewUtil.setLoadMoreEnable(true);
    }

    public class RecyclerViewAdapter extends RecyclerView.Adapter<MyViewHolder> {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
            MyViewHolder holder = new MyViewHolder(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.text.setText(data.get(position));
        }

        @Override
        public int getItemCount() {
            return data.size();
        }
    }

    private class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView text;

        public MyViewHolder(View itemView) {
            super(itemView);
            text = itemView.findViewById(android.R.id.text1);
        }
    }
}

另外,Android RecyclerView也没有实现item点击或长按事件的触发,以前我写过一篇文章,实现了该功能,《Android RecyclerView单击、长按事件:基于OnItemTouchListener +GestureDetector标准实现(二),封装抽取成通用工具类》链接:https://blog.csdn.net/zhangphil/article/details/53231344 

可以把这两套方案整合在一起,实现一个完整的Android RecyclerView工具包类。整合在一起的新RecyclerViewUtil:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by fly on 2018/3/22.
 */

public class RecyclerViewUtil {
    private boolean enable = true;
    private RecyclerView mRecyclerView;
    private OnLoadMoreListener mOnLoadMoreListener;

    private GestureDetector mGestureDetector = null;
    private RecyclerView.SimpleOnItemTouchListener mSimpleOnItemTouchListener;
    private OnItemClickListener mOnItemClickListener = null;
    private OnItemLongClickListener mOnItemLongClickListener = null;

    public RecyclerViewUtil(Context mContext, RecyclerView recyclerView) {
        this.mRecyclerView = recyclerView;

        mGestureDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
            //长按事件
            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                if (mOnItemLongClickListener != null) {
                    View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (childView != null) {
                        int position = mRecyclerView.getChildLayoutPosition(childView);
                        mOnItemLongClickListener.onItemLongClick(position, childView);
                    }
                }
            }

            //单击事件
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (mOnItemClickListener != null) {
                    View childView = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (childView != null) {
                        int position = mRecyclerView.getChildLayoutPosition(childView);
                        mOnItemClickListener.onItemClick(position, childView);
                        return true;
                    }
                }

                return super.onSingleTapUp(e);
            }
        });

        mSimpleOnItemTouchListener = new RecyclerView.SimpleOnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                if (mGestureDetector.onTouchEvent(e)) {
                    return true;
                }
                return false;
            }
        };

        mRecyclerView.addOnItemTouchListener(mSimpleOnItemTouchListener);
    }

    public void setOnLoadMoreListener(OnLoadMoreListener listener) {
        this.mOnLoadMoreListener = listener;
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                if (newState == RecyclerView.SCROLL_STATE_IDLE && isBottom(mRecyclerView)) {
                    if (enable && mOnLoadMoreListener != null) {
                        mOnLoadMoreListener.onLoadMore();
                    }
                }
            }
        });
    }

    /**
     * true 打开上拉加载 false,关闭上拉加载
     * @param enable
     */
    public void setLoadMoreEnable(boolean enable) {
        this.enable = enable;
    }

    private boolean isBottom(RecyclerView recyclerView) {
        if (recyclerView == null)
            return false;

        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
            return true;

        return false;
    }

    public interface OnLoadMoreListener {
        public void onLoadMore();
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClickListener = listener;
    }

    //长按事件接口
    public interface OnItemLongClickListener {
        public void onItemLongClick(int position, View view);
    }

    //单击事件接口
    public interface OnItemClickListener {
        public void onItemClick(int position, View view);
    }
}

新的RecyclerViewUtil实现了上拉加载更多,单击,长按事件的处理。


使用方式和上一个例子类似:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private RecyclerViewAdapter mAdapter;
    private ArrayList<String> data;

    private int START_POS = 0;
    private RecyclerViewUtil mRecyclerViewUtil;

    private Random random = new Random();

    private int MAX_COUNT = 20;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        data = new ArrayList<>();
        int count = random.nextInt(MAX_COUNT);
        for (int i = 0; i < count; i++) {
            data.add(String.valueOf(i));
        }

        START_POS = START_POS + count;

        setContentView(R.layout.activity_main);

        RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
        LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
        mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLinearLayoutManager);

        mAdapter = new RecyclerViewAdapter();
        mRecyclerView.setAdapter(mAdapter);

        mRecyclerViewUtil = new RecyclerViewUtil(this, mRecyclerView);
        mRecyclerViewUtil.setOnLoadMoreListener(new RecyclerViewUtil.OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                Toast.makeText(getApplicationContext(), "已经到底,加载更多...", Toast.LENGTH_SHORT).show();
                mRecyclerViewUtil.setLoadMoreEnable(false);
                load(START_POS, random.nextInt(MAX_COUNT));
            }
        });

        mRecyclerViewUtil.setOnItemClickListener(new RecyclerViewUtil.OnItemClickListener() {
            @Override
            public void onItemClick(int position, View view) {
                Toast.makeText(getApplicationContext(), "单击" + position, Toast.LENGTH_SHORT).show();
            }
        });

        mRecyclerViewUtil.setOnItemLongClickListener(new RecyclerViewUtil.OnItemLongClickListener() {
            @Override
            public void onItemLongClick(int position, View view) {
                Toast.makeText(getApplicationContext(), "长按" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void load(int startPos, int count) {
        for (int i = 0; i < count; i++) {
            data.add(startPos + i + "");
        }

        mAdapter.notifyDataSetChanged();
        Toast.makeText(getApplicationContext(), "加载了" + count + " 条数据", Toast.LENGTH_SHORT).show();

        START_POS = startPos + count;
        mRecyclerViewUtil.setLoadMoreEnable(true);
    }

    public class RecyclerViewAdapter extends RecyclerView.Adapter<MyViewHolder> {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(getApplicationContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
            MyViewHolder holder = new MyViewHolder(view);
            return holder;
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.text.setText(data.get(position));
        }

        @Override
        public int getItemCount() {
            return data.size();
        }
    }

    private class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView text;

        public MyViewHolder(View itemView) {
            super(itemView);
            text = itemView.findViewById(android.R.id.text1);
        }
    }
}


上一篇:Word中正文两栏表格通栏排版


下一篇:【虚拟化实战】容灾设计之三Stretched Cluster