[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 实现 微信 底部菜单

本博客地址: wukong1688

本文原文地址:https://www.cnblogs.com/wukong1688/p/10754200.html

转载请著名出处!谢谢~~

原文地址:https://www.cnblogs.com/wukong1688/p/10754200.html

时间: 2024-10-28 16:29:25

[Android] Android 支持下拉刷新、上拉加载更多 的 XRecyclerview的相关文章

十分钟实现ListView下拉刷新上滑加载更多

说到ListView下拉刷新几乎每个APP都会用到,所以ListView下拉刷新是很重要的,就像ListView优化一样是你必会的东西. ListView实现下拉刷新如果我们开发人员自己编写相对来说比较费事的,当我们使用第三方库之后我们再来开发这个功能就会省事很多.相比与自己实现可以少编写不少代码,Android-PullToRefresh库可以轻松实现ListView的下拉刷新功能. 要使用Android—PullToRefesh库对ListView实现下拉刷新要经过以下几个步骤: 1.下载A

最新Android ListView 下拉刷新 上滑加载

开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,之前大家最常用的应该是pull to refresh或它的变种版吧,google官方在最新的android.support.v4包中增加了一个新类SwipeRefreshLayout,地址 这个类的作用就是提供官方的下拉刷新,并且效果相当不错,而上拉加载更多则用我们自定义的listview,也是相当简单. 下拉刷新 简单的介绍下: 首先它是一个viewgroup,但是它只允许有一个子控件,子控件能是任何view,使用的时候,所在

Android下拉刷新库,利用viewdraghelper实现,集成了下拉刷新,底部加载更多,数据初始加载显示loading等功能

项目Github地址:https://github.com/sddyljsx/pulltorefresh Android下拉刷新库,利用viewdraghelper实现. 集成了下拉刷新,底部加载更多,以及刚进入加载数据的loadview.包括了listview与gridview的改写. 效果1: 效果2: 效果3: 效果4: 效果5: 使用说明: imageList=(ListView)findViewById(R.id.image_list); imageAdapter=new ImageA

IOS学习之UiTableView下拉刷新与自动加载更多,百年不变的效果

IOS学习之UiTableView下拉刷新与自动加载更多,百年不变的效果(五) 五一劳动节马上来临,小伙伴有妹有很激动哟,首先祝天下所有的程序猿节日快乐!这个五一对于我来说有点不一样,我的人生从这个五一就转弯了,爱情长跑8年的我结婚了,一会支付宝账号我会公布出去,请自觉打款!谢谢合作. 灯光闪起来: 舞蹈跳起来: 歌曲唱起来: -------------------------------------------------------------------------------------

Android 自定义 ListView 上下拉动&ldquo;刷新最新&rdquo;和&ldquo;加载更多&rdquo;歌曲列表

本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码太多,点击此处下载,自己调试一下. 下载 Demo 环境 Windows 2008 R2 64 位 Eclipse ADT V22.6.2,Android 4.4.3 SAMSUNG GT-I9008L,Android OS 2.2.2 测试数据 本演示的歌曲信息,共有 20 条,包括歌手名.歌曲名.时长.缩

Android ListView 下拉刷新 点击加载更多

最近项目中用到了ListView的下拉刷新的功能,总结了一下前辈们的代码,单独抽取出来写了一个demo作为示例. 效果图 下拉刷新: 加载更多: CustomListView.java [java] view plaincopy package com.example.uitest.view; import java.util.Date; import com.example.uitest.R; import android.content.Context; import android.uti

支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)

首先看效果 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个. 具体实现的效果有以下几条 下拉刷新功能:

Android 下拉刷新上啦加载SmartRefreshLayout + RecyclerView

在弄android刷新的时候,可算是耗费了一番功夫,最后发觉有现成的控件,并且非常好用,这里记录一下. 原文是 https://blog.csdn.net/huangxin112/article/details/78781682 ,这里是看了之后,结合自己实际遇到的问题写的. 首先引入包. //下拉框 implementation 'com.android.support:recyclerview-v7:28.0.0-beta01' implementation 'com.scwang.smar

Android如何定制一个下拉刷新,上滑加载更多的容器

前言 下拉刷新和上滑加载更多,是一种比较常用的列表数据交互方式. android提供了原生的下拉刷新容器 SwipeRefreshLayout,可惜样式不能定制. 于是打算自己实现一个专用的.但是下拉刷新和上滑,非常考验对android布局与父子触摸机制的功底,因此参考gitHub上的一个热门的下拉刷新项目 之所以选择他是因为它一个类就完成了所有View的适配,非常的精简强力. 需求 咱对下拉刷新.上滑加载更多的控件,需求如下: 1:下拉刷新,拖动到一定距离,提示文字变成 放手刷新 2:刷新完成

android 安卓 listview 支持下拉刷新 上拉加载更多

[1]重写listView import java.text.SimpleDateFormat; import java.util.Date; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGrou