zoukankan      html  css  js  c++  java
  • [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

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

  • 相关阅读:
    C#中如何创建文件夹,复制文件夹,删除文件夹的方法
    Entity Framework 4.1 CodeFirst 学习笔记
    c#使用豆瓣API
    字符串json转换为xml xml转换json
    基于方法的查询语法(1)
    A lowlevel Look at the ASP.NET Architecture
    删除sql表中重复数据
    关于document.cookie的使用
    大话设计模式之设计模式遵循的七大原则
    Cookies揭秘 [Asp.Net, Javascript]
  • 原文地址:https://www.cnblogs.com/wukong1688/p/10754200.html
Copyright © 2011-2022 走看看