共计 6955 个字符,预计需要花费 18 分钟才能阅读完成。
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: 人后的苦尚且还能克服,人前的尊严确无比软弱。