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);
}
}
}