[Android] Android 支持下拉刷新上拉加载更多 的 XRecyclerview
Posted wukong1688
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Android] Android 支持下拉刷新上拉加载更多 的 XRecyclerview相关的知识,希望对你有一定的参考价值。
XRecyclerView一个实现了下拉刷新,滚动到底部加载更多以及添加header功能的的RecyclerView。使用方式和RecyclerView完全一致,不需要额外的layout,不需要写特殊的adater。 加载效果内置了AVLoadingIndicatorView上的所有效果,可以根据需要指定。
效果演示如下:
插件官网地址:
https://github.com/XRecyclerView/XRecyclerView
一、添加依赖
compile \'com.jcodecraeer:xrecyclerview:1.5.9\'
二、布局文件
1) 显示的Fragment或Activity布局文件 (我这里是在Fragment文件中)
fragment_news_list.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="match_parent" android:orientation="vertical"> <com.jcodecraeer.xrecyclerview.XRecyclerView android:id="@+id/x_recycle_list" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
2)每个Item布局文件
item_news_list_style_1.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="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="120dp" android:orientation="horizontal" android:padding="16dp"> <RelativeLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center|left" android:text="标标标题标题标题标题标题题标题标题标题标题题标题标题标题标题标题" android:textColor="@color/black" android:textSize="16sp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_gravity="bottom" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/tv_cate_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="今日新闻" android:textSize="12sp" /> <TextView android:id="@+id/tv_read_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/tv_cate_name" android:text="100" android:textSize="12sp" /> <ImageView android:id="@+id/iv_delete" android:layout_width="20dp" android:layout_height="12dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_gravity="right" android:background="@mipmap/ic_article_delete" /> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:layout_toLeftOf="@id/iv_delete" android:text="刚刚" android:textSize="12sp" /> </RelativeLayout> </RelativeLayout> <ImageView android:id="@+id/iv_main_img" android:layout_width="130dp" android:layout_height="match_parent" android:layout_gravity="center" android:layout_marginLeft="10dp" android:src="@mipmap/img_show" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@color/tv_line" /> </LinearLayout>
三、Adapter类实现
NewsListRecycleAdapter.java (与普通的RecycleListView 的Adapter 类似)
package com.jack.appnews.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.jack.appnews.R; import com.jack.appnews.bean.ItemNewsBean; import com.jcodecraeer.xrecyclerview.XRecyclerView; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; public class NewsListRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<ItemNewsBean> items; private ClickListener clickListener; public NewsListRecycleAdapter(Context context, List<ItemNewsBean> items) { this.context = context; this.items = items; } public interface ClickListener { void onItemClick(View v, int position); } public void setOnItemClickListener(ClickListener clickListener) { this.clickListener = clickListener; } @Override public XRecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; RecyclerView.ViewHolder viewHolder = null; switch (viewType) { case 1: view = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_news_list_style_1, parent, false); viewHolder = new ViewHolderOne(view); break; } return viewHolder; } @Override public void onBindViewHolder(final XRecyclerView.ViewHolder holder, int position) { ItemNewsBean newsBean = items.get(position); switch (getItemViewType(position)) { case 1: //1张图 情况 ViewHolderOne ViewHolderOne = (ViewHolderOne) holder; ViewHolderOne.tvTitle.setText(newsBean.getNews_title()); ViewHolderOne.tvCateName.setText(newsBean.getSource_name()); if (newsBean.getImg_list() != null && newsBean.getImg_list().size() > 0) { Glide.with(context) .load(newsBean.getImg_list().get(0)) .error(R.mipmap.ic_article_delete) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(ViewHolderOne.ivImage); } break; } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); clickListener.onItemClick(holder.itemView, pos); } }); } @Override public int getItemViewType(int position) { return items.get(position).getContent_type(); } @Override public long getItemId(int position) { return position; } @Override public int getItemCount() { return items.size(); } //1张图 public static class ViewHolderOne extends RecyclerView.ViewHolder { @BindView(R.id.tv_title) TextView tvTitle; @BindView(R.id.tv_cate_name) TextView tvCateName; @BindView(R.id.iv_main_img) ImageView ivImage; public ViewHolderOne(View view) { super(view); ButterKnife.bind(this, view); } } }
四、主界面文件调用
NewsListFragment.java (为方便测试,将数据都写死在文件中)
package com.jack.appnews.ui.fragment; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.view.View; import android.widget.Toast; import com.jack.appnews.R; import com.jack.appnews.adapter.NewsListRecycleAdapter; import com.jack.appnews.bean.ItemNewsBean; import com.jack.appnews.ui.BaseFragment; import com.jcodecraeer.xrecyclerview.ProgressStyle; import com.jcodecraeer.xrecyclerview.XRecyclerView; import java.util.ArrayList; import java.util.Collections; import java.util.List; import butterknife.BindView; /** * 新闻列表 */ public class NewsListFragment extends BaseFragment { @BindView(R.id.x_recycle_list) XRecyclerView mRecyclerView; private NewsListRecycleAdapter mAdapter; private List<ItemNewsBean> mList = new ArrayList<>(); private List<String> imgList1 = new ArrayList<>(); private List<String> imgList2 = new ArrayList<>(); private int times = 0; @Override protected int inflateLayoutId() { return R.layout.fragment_news_list; } @Override protected void prepare() { genImgList(); } protected void initViews() { //1)初始化RecyclerView设置 mRecyclerView.setPullRefreshEnabled(true); mRecyclerView.setLoadingMoreEnabled(true); mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallClipRotate); //2)添加布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(layoutManager); //3)配置Adapter mList = genData(); mAdapter = new NewsListRecycleAdapter(getContext(), mList); mRecyclerView.setAdapter(mAdapter); //4) 监听 点击,注意是监听 mAdapter ,而不是 mRecyclerView mAdapter.setOnItemClickListener(new NewsListRecycleAdapter.ClickListener() { @Override public void onItemClick(View v, int position) { Toast.makeText(getContext(), "click, pos:" + position, Toast.LENGTH_LONG).show(); } }); //5)实现 下拉刷新和加载更多 接口 mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() { @Override public void onRefresh() { times = 0; new Handler().postDelayed(new Runnable() { @Override public void run() { mList.clear(); //先要清掉数据 List<ItemNewsBean> list = genRefreshData(); mList.addAll(list); //再将数据插入到前面 mAdapter.notifyDataSetChanged(); mRecyclerView.refreshComplete(); //下拉刷新完成 Toast.makeText(getContext(), "刷新完成,新加" + list.size() + "条新闻", Toast.LENGTH_SHORT).show(); } }, 1000); } @Override public void onLoadMore() { if (times < 20) {//加载20次后,就不再加载更多 new Handler().postDelayed(new Runnable() { public void run() { List<ItemNewsBean> list = genLoadMoreData(); mList.addAll(list); //直接将数据追加到后面 Toast.makeText(getContext(), "加载完成,新加" + list.size() + "条新闻", Toast.LENGTH_SHORT).show(); mRecyclerView.loadMoreComplete(); mAdapter.notifyDataSetChanged(); } }, 1000); } else { new Handler().postDelayed(new Runnable() { public void run() { List<ItemNewsBean> list = genLoadMoreData(); mList.addAll(list); //将数据追加到后面 mAdapter.notifyDataSetChanged(); mRecyclerView.setNoMore(true); } }, 1000); } times++; } }); } /** * 初始化需要显示的图片 */ private void genImgList() { imgList1.add("http://p3-tt.bytecdn.cn/list/300x196/pgc-image/ROLsHtn2l4vdxK"); imgList2.add("http://p3-tt.bytecdn.cn/list/300x196/1f50e0009802d39b66b76"); } @NonNull /** * 生成数据实例 */ private List<ItemNewsBean> genData() { List<ItemNewsBean> mList = new ArrayList<>(); mList.add(new ItemNewsBean("奔驰之后是宝马,汽车“召回”和“不召回”哪个更可怕?", "央视网", imgList1, 1)); mList.add(new ItemNewsBean("全台所有村长遭恐吓:访大陆如签协议,将被罚50万", "大连阳光新闻网", 1)); mList.add(new ItemNewsBean("中国驻斯里兰卡大使馆:中国公民确认死亡人数修正为1人", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("特斯拉回应车辆自燃:已联络车主 最大努力协助善后", "一起来育儿", imgList2, 1)); mList.add(new ItemNewsBean("中国驻斯里兰卡大使馆:中国公民确认死亡人数修正为1人", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("住建部预警房价地价波动较大城市 部分区域楼市调控或升级", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("中国驻斯里兰卡大使馆:中国公民确认死亡人数修正为1人", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("全台所有村长遭恐吓:访大陆如签协议,将被罚50万", "大连阳光新闻网", 1)); mList.add(new ItemNewsBean("特斯拉回应车辆自燃:已联络车主 最大努力协助善后", "一起来育儿", imgList2, 1)); Collections.shuffle(mList);//打乱顺序输出,为了美观 return mList; } private List<ItemNewsBean> genRefreshData() { List<ItemNewsBean> mList = new ArrayList<>(); mList.add(new ItemNewsBean("刷新数据:中石化新任总经理,有颗小行星以他命名", "腾讯新闻网", imgList1, 1)); mList.add(new ItemNewsBean("刷新数据:互联护苗·2019活动启动", "一点咨询新闻", imgList2, 1)); mList.add(new ItemNewsBean("刷新数据:全台所有村长遭恐吓:访大陆如签协议,将被罚50万", "大连阳光新闻网", 1)); mList.add(new ItemNewsBean("刷新数据:中国驻斯里兰卡大使馆:中国公民确认死亡人数修正为1人", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("刷新数据:住建部预警房价地价波动较大城市 部分区域楼市调控或升级", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("刷新数据:中国驻斯里兰卡大使馆:中国公民确认死亡人数修正为1人", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("刷新数据:住建部之所以对部分热点城市发出预警,意在对市场预期进行适度引导", "一点咨询新闻", 1)); mList.add(new ItemNewsBean("刷新数据:其他政策的调整对楼市影响将相对有限", "一点咨询新闻", 1)); Collections.shuffle(mList);//打乱顺序输出,为了美观 return mList; } private List<ItemNewsBean> genLoadMoreData() { List<ItemNewsBean> mList = new ArrayList<>(); mList.add(new ItemNewsBean("加载数据:清华大学:博士生不再强制要求在学期间发表论文", "百度新闻网", imgList1, 1)); mList.add(new ItemNewsBean("加载数据:这几位部长去了同一个地方,事关高层部署", "一点咨询新闻", 1)); Collections.shuffle(mList);//打乱顺序输出,为了美观 return mList; } @Override public void onDestroy() { super.onDestroy(); if (mRecyclerView != null) { mRecyclerView.destroy(); mRecyclerView = null; } } }
基本核心代码,都在上述文件中 红色字体 标明!
五、最后附上Github 代码地址:
https://github.com/wukong1688/Android-BaseTabHost
这是我用FragmentTabHost + ViewPager + XRecycleList 实现的 标签切换 + 列表上滑加载+列表下滑刷新
其中 标签切换 可参考上一篇文章:
Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单
以上是关于[Android] Android 支持下拉刷新上拉加载更多 的 XRecyclerview的主要内容,如果未能解决你的问题,请参考以下文章
Android 怎么实现支持所有View的通用的下拉刷新控件