RecyclerView多层嵌套列表的实现,加下拉刷新上拉加载。
2020-12-14 本文已影响0人
永远爱你ol
RecyclerView是安卓中比较常用的列表控件了,当然刚接触这个控件的时候肯定也会遇到很多问题。接下来分享一下自己遇到的问题和解决方法。
20201214-135552.png
像上图这种列表就需要双层嵌套了,接下来我们先创建RecyclerView控件。
RecyclerView ListView = (RecyclerView)findViewById(R.id.adapter_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
ListView.setLayoutManager(layoutManager);
ListView.addItemDecoration(new SpacesItemDecoration(14));
adapter = new JiankangpersonAdapter(DActivity.this,heathList);
ListView.setAdapter(adapter);
appRefresh();//下拉刷新
EndLessOnScrollListener.reSet(); //上拉加载
ListView.addOnScrollListener(new EndLessOnScrollListener(layoutManager) {
@Override
public void onLoadMore(int currentPage) {
//需要加载的数据
}
});
附上对应的adapt的代码,其中包括了实现上拉加载的功能。
public class JiankangpersonAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private List<HeathpersonUserinfo> mDatas;
private Context context;
private int normalType = 0; // 第一种ViewType,正常的item
private int footType = 1; // 第二种ViewType,底部的提示View
private boolean fadeTips = false; // 变量,是否隐藏了底部的提示
public JiankangpersonAdapter(Context context, List<HeathpersonUserinfo> data){
mDatas = data;
this.context = context;
}
class NormalHolder extends RecyclerView.ViewHolder {
public TextView date;
public RecyclerView persondetailList;
public NormalHolder(View v) {
super(v);
date=(TextView)v.findViewById(R.id.person_date);
persondetailList = (RecyclerView)v.findViewById(R.id.jiankangpersoninfo_list);
}
}
class FootHolder extends RecyclerView.ViewHolder {
private TextView tips;
public FootHolder(View itemView) {
super(itemView);
tips = (TextView) itemView.findViewById(R.id.tips);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == normalType) {
NormalHolder normalHolder =new NormalHolder (LayoutInflater.from(parent.getContext()).inflate(R.layout.view_jiankangperson, parent, false));
return normalHolder;
}else{
return new FootHolder(LayoutInflater.from(context).inflate(R.layout.foot_item, null));
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof NormalHolder) {
HeathpersonUserinfo huser = mDatas.get(position);
((NormalHolder)holder).date.setText(huser.getDate());
((NormalHolder)holder).date.setTextColor(Color.parseColor("#557ac4"));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Toast.makeText(context, "点击了", Toast.LENGTH_SHORT).show();
}
});
((NormalHolder)holder).persondetailList.setLayoutManager(new LinearLayoutManager(context));
//holder.persondetailList.addItemDecoration(new SpacesItemDecoration(4));
final JiankangpersonInfoAdapter checkinfoAdapter = new JiankangpersonInfoAdapter(context,huser.getPersondetail());
((NormalHolder)holder).persondetailList.setAdapter(checkinfoAdapter);
}else{
((JiankangpersonAdapter.FootHolder) holder).tips.setVisibility(View.VISIBLE);
if (EndLessOnScrollListener.isHasMore() == false) {
fadeTips = false;
if (mDatas.size() > 0) {
((JiankangpersonAdapter.FootHolder) holder).tips.setText("正在加载更多...");
}
} else {
if (mDatas.size() > 0) {
((JiankangpersonAdapter.FootHolder) holder).tips.setText("没有更多数据了");
}else {
((JiankangpersonAdapter.FootHolder) holder).tips.setVisibility(View.GONE);
}
}
}
}
@Override
public int getItemCount() {
return mDatas.size()+1;
}
@Override
public int getItemViewType(int position) {
if (position == getItemCount() - 1) {
return footType;
} else {
return normalType;
}
}
}
最关键的是这一部分,在最后加上这段代码,就可以实现在当前列表循环之下,再嵌套一层循环。
((NormalHolder)holder).persondetailList.setLayoutManager(new LinearLayoutManager(context));
final JiankangpersonInfoAdapter checkinfoAdapter = new JiankangpersonInfoAdapter(context,huser.getPersondetail());
((NormalHolder)holder).persondetailList.setAdapter(checkinfoAdapter);
因为JiankangpersonInfoAdapter中不需要添加上拉加载的功能,所以adapter的结构是有所区别的(结构示例如下)。
public class JiankangpersonInfoAdapter extends RecyclerView.Adapter<JiankangpersonInfoAdapter.VH>{
static class VH extends RecyclerView.ViewHolder{
public TextView type1;
public TextView typekuohao;
public VH(View v) {
super(v);
type1=(TextView)v.findViewById(R.id.jiankang_info_type);
typekuohao=(TextView)v.findViewById(R.id.jiankang_info_typekuohao);
}
}
private List<CheckInfo> mDatas;
private Context context;
public JiankangpersonInfoAdapter(Context context, List<CheckInfo> data){
mDatas = data;
this.context = context;
}
@NonNull
@Override
public JiankangpersonInfoAdapter.VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_jiankangperson_info, parent, false);
final JiankangpersonInfoAdapter.VH holder = new JiankangpersonInfoAdapter.VH(v);
return holder;
}
@Override
public void onBindViewHolder(@NonNull VH holder, int position) {
holder.type1.setText("起床");
holder.typekuohao.setText("(生活)");
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Toast.makeText(context, "点击了详情", Toast.LENGTH_SHORT).show();
}
});
}
public List<HeathpersonRecorddetail> initData(String recordId){
List<HeathpersonRecorddetail> heathList = new ArrayList<HeathpersonRecorddetail>();
return heathList;
}
@Override
public int getItemCount() {
return mDatas.size();
}
// 删除数据
public void removeData(int position) {
mDatas.remove(position);
//删除动画
notifyItemRemoved(position);
notifyDataSetChanged();
}
//dp转px
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
下拉刷新首先添加如下代码。
private SwipeRefreshLayout swipeRefreshLayout;
Handler handlerForRefresh = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0x93: {
swipeRefreshLayout.setRefreshing(false);
}
}
}
};
然后是appRefresh()方法。
private void appRefresh(){
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setColorSchemeResources(R.color.blue);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Thread(){
@Override
public void run () {
super.run();
//同步加载网络数据
//加载数据 完毕后 关闭刷新状态 切回主线程
handlerForRefresh.postDelayed(new Runnable() {
@Override
public void run() {
//需要刷新的数据
EndLessOnScrollListener.reSet();//重置上拉加载的设置
// 通知结束下拉刷新
handlerForRefresh.sendEmptyMessage(0x93);
}
}, 100);
}
}.start();
}
});
}
其中swipe_refresh_layout是需要在xml文件中添加的。
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/jiankang_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
上拉加载中关键的类 EndLessOnScrollListener。
public abstract class EndLessOnScrollListener extends RecyclerView.OnScrollListener{
//声明一个LinearLayoutManager
private LinearLayoutManager mLinearLayoutManager;
//当前页,从0开始
private static int currentPage = 1;
//已经加载出来的Item的数量
private static int totalItemCount;
//主要用来存储上一个totalItemCount
private static int previousTotal;
//在屏幕上可见的item数量
private static int visibleItemCount;
//在屏幕可见的Item中的第一个
private static int firstVisibleItem;
//是否正在上拉数据
private static boolean loading = true;
private static boolean hasMore=true;
private int recordFlag=0;
public EndLessOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if(recordFlag!=0){
if(loading){
if(totalItemCount > previousTotal){
//说明数据已经加载结束
hasMore=false;
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && totalItemCount-visibleItemCount <= firstVisibleItem){
hasMore=true;
currentPage ++;
onLoadMore(currentPage);
loading = true;
}
}
recordFlag++;
}
public static void reSet(){
currentPage=1;
totalItemCount=0;
previousTotal=0;
visibleItemCount=0;
firstVisibleItem=0;
loading=true;
hasMore=true;
}
public static boolean isHasMore() {
return hasMore;
}
/**
* 提供一个抽闲方法,在Activity中监听到这个EndLessOnScrollListener
* 并且实现这个方法
* */
public abstract void onLoadMore(int currentPage);}
注:其中关于页面的xml文件在这边全部省略了。