Android 提供的Swiperefreshlayout 实现下拉刷新和RecyclerView上拉加载更多
一:简介
SwipeRefrshLayout是Google官方更新的一个控件,可以实现下拉刷新的效果
添加依赖首先在应用或模块的build.gradle文件中添加所需的工作依赖项:
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"//添加依赖
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tv_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
二:Swiperefreshlayout实现下拉加载更多
setColorSchemeResources(int... colorResIds):设置下拉进度条的颜色主题,参数为可变参数,并且是资源id,可以设置多种不同的颜色,每转一圈就显示一种颜色。
setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener):设置监听,需要重写onRefresh()方法,顶部下拉时会调用这个方法,在里面实现请求数据的逻辑,设置下拉进度条消失等等。
setProgressBackgroundColorSchemeResource(int colorRes):设置下拉进度条的背景颜色,默认白色。
setRefreshing(boolean refreshing):设置刷新状态,true表示正在刷新,false表示取消刷新。
使用:
private SwipeRefreshLayout swipe_refresh;
swipe_refresh=findViewById(R.id.swipe_refresh);
swipe_refresh.setColorSchemeResources(new int[]{R.color.start,R.color.min,R.color.end});//设置下拉进度条颜色
swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//延迟2秒设置不刷新,模拟耗时操作,需要放在子线程中
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// myRecycleViewAdapter.addData(0);
myRecycleViewAdapter.add(mInsertDatas);//添加一个数据集合
// myRecycleViewAdapter.notifyDataSetChanged();
swipe_refresh.setRefreshing(false);//设置是否刷新
}
},2000);
}
});
}
构建假的数据集合
private List<String> mInsertDatas=new ArrayList<>();
for (int j=0;j<10;j++){
mInsertDatas.add("我是Insert Data"+j);
}
调用适配器的add方法
/**
* 添加数据集合到数据集合中
*/
public void add(List<String> datas) {
//mDatas.addAll(datas);//这个会把数据加载末尾
mDatas.addAll(0,datas);//这个添加数据集合到头
notifyDataSetChanged();
}
RecyclerView 的滑动状态有如下三种状态:
public static final int SCROLL_STATE_IDLE = 0;//手指离开屏幕
public static final int SCROLL_STATE_DRAGGING = 1;//手指触摸屏幕
public static final int SCROLL_STATE_SETTLING = 2;//手指加速滑动并放开,此时滑动状态伴随SCROLL_STATE_IDLE
三:Swiperefreshlayout配合RecyclerView实现上拉加载更多
/**RecyclerView使用滚动监听*/
tv_recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
/**
* 当RecyclerView的滑动状态改变时触发
*/
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Log.d("test", "StateChanged = " + newState);
//如果想通过指尖滑动屏幕变化来判断是否触碰,实现当且仅当滑动到最后一项并且手指上拉抛出时才执行上拉加载更多效果的话,需要配合onScrollStateChanged(RecyclerView recyclerView, int newState的使用,
//if (newState==RecyclerView.SCROLL_STATE_IDLE)来判断
}
/**
* 当RecyclerView滑动时触发
* 类似点击事件的MotionEvent.ACTION_MOVE
*/
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
if (lastVisibleItemPosition+1==myRecycleViewAdapter.getItemCount()){
Log.d("test", "loading executed");
boolean isRefreshing=swipe_refresh.isRefreshing();
if (isRefreshing){
myRecycleViewAdapter.notifyItemRemoved(myRecycleViewAdapter.getItemCount());
return;
}
if (!isLoading){
isLoading=true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getData();
Log.d("test", "load more completed");
isLoading = false;
}
},1000);
}
}
}
});
}
获取假数据
/**获取测试数据*/
private void getData() {
for (int i=0;i<6;i++){
mDatas.add("我是加载更多数据"+i);
}
myRecycleViewAdapter.notifyDataSetChanged();
swipe_refresh.setRefreshing(false);
}
//对应的Adapter增加了脚布局ViewHolder实现加载最后显示叫布局
public class MyRecycleViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<String> mDatas;//数据源
private Context context;
private static final int TYPE_ITEM = 0;//定义非加载更多
private static final int TYPE_FOOTER = 1;//加载更多
private OnItemClickListener onItemClickListener;
/**
* 向外部提供调用设置监听
*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public MyRecycleViewAdapter(Context context, List<String> mDatas) {
this.context = context;
this.mDatas = mDatas;
}
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
/**
* 创建ViewHolder并返回,后续item布局里控件都是从ViewHolder中取出
*/
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_FOOTER) {
//将我们自定义的脚布局转成View
View view_foot = LayoutInflater.from(context).inflate(R.layout.item_foot, parent, false);
//将View传递给我们自定义脚FootViewHolder
return new FootViewHolder(view_foot);
} else if (viewType == TYPE_ITEM) {
//将我们自定义的item布局转成View
View view = LayoutInflater.from(context).inflate(R.layout.item_one, parent, false);
//将View传递给我们自定义ViewHolder
return new MyHolder(view);
}
return null;
}
/**
* 通过方法提供的ViewHolder,将数据绑定到的ViewHolder中
*/
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyHolder){
((MyHolder) holder).tv_content.setText(mDatas.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(v, holder.getAdapterPosition() + 1);
}
}
});
}
}
/**
* 添加一条数据到index 0数据
*/
public void addData(int position) {
mDatas.add(position, "Insert" + position);
notifyItemInserted(position);////通知插入的位置
if (position != getItemCount()) {
notifyItemRangeChanged(position, getItemCount());//排序插入位置到末尾
}
}
/**
* 添加数据集合到数据集合中
*/
public void add(List<String> datas) {
//mDatas.addAll(datas);
mDatas.addAll(0, datas);
notifyDataSetChanged();
}
/**
* 获取数据源总的条目
*/
@Override
public int getItemCount() {
return mDatas.size();
}
static class MyHolder extends RecyclerView.ViewHolder {
TextView tv_content;
public MyHolder(@NonNull View itemView) {
super(itemView);
tv_content = itemView.findViewById(R.id.tv_content);
}
}
/**脚布局的ViewHolder*/
static class FootViewHolder extends RecyclerView.ViewHolder {
public FootViewHolder(@NonNull View itemView) {
super(itemView);
}
}
/**
* 自定义的接口
*/
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
}
对应的脚布局View,item_foot.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:layout_marginRight="6dp"
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="加载更多" />
</LinearLayout>
结果:
在Adapter中
对应想添加一条数据,或者删除一条数据
/**删除一条数据*/
public void removeData(int position){
mDatas.remove(position);
notifyItemRemoved(position);//第position个被删除的时候刷新
//notifyItemRangeRemoved(1,10);//批量删除
if (position!=getItemCount()){
notifyItemRangeChanged(position,getItemCount());//可以刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)。
}
}
/**
* 添加一条数据到index 0数据
*/
public void addData(int position) {
mDatas.add(position, "Insert" + position);
notifyItemInserted(position);//通知插入的位置
if (position != getItemCount()) {
notifyItemRangeChanged(position, getItemCount());//排序插入位置到末尾
}
}
END:人后的苦尚且还能克服,人前的尊严确无比脆弱。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。