LowRecyclerView:一个简单强大的RecyclerView工具类

来源:互联网 发布:淘宝死多少人 编辑:程序博客网 时间:2024/06/05 06:21

尊重原创,转载注明:http://blog.csdn.net/qq_35980424/article/details/72899985


  在开发过程中我们经常使用Listview、GridView等以列表来展示我们APP的信息,可以带给用户更好的体验。在以前的开发过程中我一直都是使用的封装好的Adapter,使用起来比较方便,所以就对RecyclerView没有太了解。但是一直听周围的小伙伴们说RecyclerView多么的强大,所以就按捺不住好奇心去深入了解了一下,结果就彻底的迷恋上了RecyclerView。但是RecyclerView不进行封装使用起来也是挺麻烦的,许多小伙伴们使用RecyclerView的时候,每一个列表都写了一个adapter,这样一来不但写起来耗时,最关键的是增加了代码的重复率,这对与我这种懒逼来说不可接受。但是看了许多第三方的开源框架,有的项目很大扩展起来十分麻烦,有的性能不是那么完美,作为一个外包性质的程序员来说效率和质量才是最重要的,所以我就利用我的空闲时间来搭建RecyclerView的通用工具类,经过两个月的努力,我们强大的LowRecyclerView终于面世了。

1.LowRecyclerView优点:

  使用LowRecyclerView能够帮您将代码复写率缩减至少60%,缩短项目周期至少40%(这里只指ListView、GridView列表等,不包含其他)。LowRecyclerView采用mvp的设计模式,具有高度的灵活性。只需简单的设置就能实现如下功能,项目维护更加方便。实现的主要功能有:

 1.ListView(支持添加不同的HeaderView、FooterView和自定义颜色分割线)
 2.GridView(支持添加不同的HeaderView、FooterView和自定义颜色分割线)
 3.WaterFall(瀑布流:支持添加不同的HeaderView、FooterView和自定义颜色分割线)
 4.HorizontalListView(添加自定义颜色分割线)
 5.HorizontalGridView(添加自定义颜色分割线)
 6.HorizontalWaterFall(添加自定义颜色分割线)
 7.所有效果均支持item和childView的长按或者短按点击事件

2.ListView的实现:

 首先将LowRecyclerView添加到您的项目中去,github地址和Demo地址在本文末尾,导入方法详见github。

  实现ListView效果:

  这里先讲解如何设置LowRecyclerView显示ListView,下面会讲解如何添加HaederView和FooterView、添加分割线和点击事件。 

  首先看布局文件的设置,这里和我们平常使用时没有什么区别,代码如下:

<?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">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scrollbars="none"        android:background="@color/gray"        >    </android.support.v7.widget.RecyclerView></LinearLayout>


  再来看我们的Item布局:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="10dp"android:background="@color/w"    ><ImageView    android:id="@+id/item_image"    android:layout_width="80dp"    android:layout_height="80dp"    /><TextView    android:id="@+id/item_title"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_toRightOf="@id/item_image"    android:layout_marginTop="10dp"    android:layout_marginBottom="10dp"    /><TextView    android:id="@+id/item_content"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_toRightOf="@id/item_image"    android:layout_below="@id/item_title"    android:layout_marginTop="10dp"    /></RelativeLayout>


接下来就是见证奇迹的时候了,这里我们用假数据来模拟网络数据,图片均来自网上,如有侵权请联系我。

 list = new ArrayList<>();        list.add(new Test("title", "http://d.5857.com/xgs_150428/001.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/002.jpg", "内容"));        list.add(new Test("title", "https://a-ssl.duitang.com/uploads/item/201502/27/20150227112432_jcwSt.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/003.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/004.jpg", "内容"));        list.add(new Test("title", "https://b-ssl.duitang.com/uploads/item/201502/27/20150227112439_jZRcF.thumb.700_0.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/005.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/006.jpg", "内容"));        list.add(new Test("title", "https://b-ssl.duitang.com/uploads/item/201502/27/20150227112459_3WJeZ.thumb.700_0.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/007.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/008.jpg", "内容"));


List集合中的Test类如下:

package com.liuxiaozhu.testlowrecyclerview.bean;/** * Created by chenhui on 2017/6/9. * All Rights Reserved by YiZu * 通过该类存放数据 */public class Test {    private String title;    private String img;    private String content;    public Test(String title, String img, String content) {        this.title = title;        this.img = img;        this.content = content;    }    public Test(String img) {        this.img = img;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getImg() {        return img;    }    public void setImg(String img) {        this.img = img;    }    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;    }}


开始编写Adapter,这里我们需要将Context,ListView显示的数据集合list,Item的布局Id以及RecyclerView显示的方式ListView四个参数传进去,在setData方法里对每个Item进行设置。(关于CommonRecyclerAdapter和RecyclerVViewStytle更详细的解释请移步github)

adapter = new CommonRecyclerAdapter<Test>(this, list, R.layout.list_item, RecyclerViewStyle.ListView) {            @Override            protected void setData(BaseRecycleViewsHolder holder, int position, Test item) {                //这里对listview每个itme中的子控件设置值                holder.getTextView(R.id.item_title).setText(item.getTitle() + position);                holder.getTextView(R.id.item_content).setText(item.getContent() + position);                Picasso.with(mContext)                        .load(item.getImg())                        .into(holder.getImageView(R.id.item_image));            }            @Override            protected void setFootData(BaseRecycleViewsHolder holder, int position, int footposition) {//                设置每个footerview的数据()            }            @Override            protected void setHeadData(BaseRecycleViewsHolder holder, int position) {//                设置每个headerview的数据            }        };        recyclerView.setAdapter(adapter);//***非常重要,不要忘记

我们setAdapter后,实例化RecyclerViewsUtils,这里我们需要传入3个参数RecyclerView、adapter和列数(ListView可随便传,GridView和WaterFall显示的行数或列数是这里进行控制)

new RecyclerViewUtils<>(recyclerView, adapter, 1);

ok到这里我们的ListView已经写好了,运行一下就可以看到一个漂亮的ListView出现在你的app上了,效果已经给出。

那么如何添加Item的点击事件呢?我们只需要在adapter的setData方法里调用一个方法给Item设置监听事件:

holder.setItemClickListener();

然后调用adapter里的方法就可以设置点击事件了

adapter.setOnItemClick(new OnItemClick() {            @Override            public void onItemClick(int position, View view, BaseRecycleViewsHolder holder) {                //这里设置Item点击事件            }        });

Item的长按事件处理方式和上述方法类似,在adapter的setData方法里调用Item的长按监听:

holder.setItemLongClickListener();

然后调用如下方法设置点击长按事件:

adapter.setOnItemLongClick(new OnItemLongClick() {            @Override            public void onItemLongClick(int i, View view, BaseRecycleViewsHolder baseRecycleViewsHolder) {                //这里设置Item长按点击事件            }        });

Item的子view(childView)的设置方法和Item设置相同,我们需要传入要监听的子View的Id,长按监听为

holder.setLongClickListener(R.id.item_image);

短按监听为

holder.setClickListener(R.id.item_image);

Item的子view点击事件处理和Item基本相同,方法如下:

adapter.setOnClick(new OnClick() {            @Override            public void onClick(int position, View view, BaseRecycleViewsHolder holder) {                //子View点击事件的处理            }        });
adapter.setOnLongClick(new OnLongClick() {            @Override            public void onLongClick(int i, View view, BaseRecycleViewsHolder baseRecycleViewsHolder) {               //子View长按点击事件的处理             }        });

到这里我们的LowRecyclerView实现的ListView已经具备了点击事件,那么接下来我们来为我们的ListView添加分割线,这里我们只需调用一个方法就可以搞定,这里我们需要传入分割线的高度和颜色。有关分割线的具体原理请移步我的另一篇文章:http://blog.csdn.net/qq_35980424/article/details/73500829

代码如下:

new RecyclerViewUtils<>(recyclerView, adapter, 1).addItemDecoration(5,R.color.colorAccent);

来看效果:



ok我们可以看得到最后一个Item后面是没有分割线的,那么接下来我们就来给我们的ListView来添加HeaderView和FooterView,使用LowRecyclerView可以实现添加多个不同的HeadView和FooterView,我们需要如下两个方法:

//添加HeaderView和FooterView        adapter.addHeaderView(R.layout.head);        adapter.addHeaderView(R.layout.head1);        adapter.addHeaderView(R.layout.head);        adapter.addFooterView(R.layout.head);        adapter.addFooterView(R.layout.head1);        adapter.addFooterView(R.layout.head);

然后分别在adapter里的setHeadData和setFootView设置数据,代码如下:

@Override            protected void setFootData(BaseRecycleViewsHolder holder, int position, int footposition) {//                设置每个footerview的数据()                if (footposition == 1) {                    holder.getTextView(R.id.head1_text).setText("我是foot"+footposition);                } else {                    Picasso.with(mContext)                            .load("https://b-ssl.duitang.com/uploads/item/201404/15/20140415093636_Rdr3x.jpeg")                            .fit()                            .into(holder.getImageView(R.id.imageview));                }                //给Footer的Item设置监听                holder.setItemClickListener();            }            @Override            protected void setHeadData(BaseRecycleViewsHolder holder, int position) {//                设置每个headerview的数据                if (position == 1) {                    holder.getTextView(R.id.head1_text).setText("我是Header" + position);                } else {                    Picasso.with(mContext)                            .load("https://b-ssl.duitang.com/uploads/item/201404/15/20140415093636_Rdr3x.jpeg")                            .fit()                            .into(holder.getImageView(R.id.imageview));                }                //给Header的Item设置监听                holder.setItemClickListener();            }        };

这里由于设置了不同的HeaderView和FooterView,我们需要根据position来设置我们的HeaderView和FooterView。若添加了相同的HeaderView和FooterView,数据设置可以参考setData方法,设置监听的方法和ListView相同,这里不再叙述。另外,如果添加了HeadView,posiotion为0是代表是第一个HeaderView。最终的效果如下:


全部代码如下:

public class ListViewActivity extends AppCompatActivity {    private RecyclerView recyclerView;    private CommonRecyclerAdapter<Test> adapter;    private List<Test> list;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_base);        initView();        setdata();        setLisinter();    }    private void setLisinter() {        //item的子view点击事件        adapter.setOnClick(new OnClick() {            @Override            public void onClick(int position, View view, BaseRecycleViewsHolder holder) {                Toast.makeText(adapter.getContext(), "您点击了图片" + position, Toast.LENGTH_SHORT).show();            }        });//        item点击事件        adapter.setOnItemClick(new OnItemClick() {            @Override            public void onItemClick(int position, View view, BaseRecycleViewsHolder holder) {                Toast.makeText(adapter.getContext(), "您点击了item" + position, Toast.LENGTH_SHORT).show();            }        });    }    private void setdata() {        list = new ArrayList<>();        list.add(new Test("title", "http://d.5857.com/xgs_150428/001.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/002.jpg", "内容"));        list.add(new Test("title", "https://a-ssl.duitang.com/uploads/item/201502/27/20150227112432_jcwSt.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/003.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/004.jpg", "内容"));        list.add(new Test("title", "https://b-ssl.duitang.com/uploads/item/201502/27/20150227112439_jZRcF.thumb.700_0.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/005.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/006.jpg", "内容"));        list.add(new Test("title", "https://b-ssl.duitang.com/uploads/item/201502/27/20150227112459_3WJeZ.thumb.700_0.jpeg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/007.jpg", "内容"));        list.add(new Test("title", "http://d.5857.com/xgs_150428/008.jpg", "内容"));        adapter = new CommonRecyclerAdapter<Test>(this, list, R.layout.list_item, RecyclerViewStyle.ListView) {            @Override            protected void setData(BaseRecycleViewsHolder holder, int position, Test item) {                //这里对listview每个itme中的子控件设置值                holder.getTextView(R.id.item_title).setText(item.getTitle() + position);                holder.getTextView(R.id.item_content).setText(item.getContent() + position);                Picasso.with(mContext)                        .load(item.getImg())                        .into(holder.getImageView(R.id.item_image));                //给ImageView设置点击事件监听                holder.setClickListener(R.id.item_image);                holder.setItemClickListener();            }            @Override            protected void setFootData(BaseRecycleViewsHolder holder, int position, int footposition) {//                设置每个footerview的数据()                if (footposition == 1) {                    holder.getTextView(R.id.head1_text).setText("我是foot"+footposition);                } else {                    Picasso.with(mContext)                            .load("https://b-ssl.duitang.com/uploads/item/201404/15/20140415093636_Rdr3x.jpeg")                            .fit()                            .into(holder.getImageView(R.id.imageview));                }                //给Footer的Item设置监听                holder.setItemClickListener();            }            @Override            protected void setHeadData(BaseRecycleViewsHolder holder, int position) {//                设置每个headerview的数据                if (position == 1) {                    holder.getTextView(R.id.head1_text).setText("我是Header" + position);                } else {                    Picasso.with(mContext)                            .load("https://b-ssl.duitang.com/uploads/item/201404/15/20140415093636_Rdr3x.jpeg")                            .fit()                            .into(holder.getImageView(R.id.imageview));                }                //给Header的Item设置监听                holder.setItemClickListener();            }        };        recyclerView.setAdapter(adapter);//***非常重要,不要忘记        //添加HeaderView和FooterView        adapter.addHeaderView(R.layout.head);        adapter.addHeaderView(R.layout.head1);        adapter.addHeaderView(R.layout.head);        adapter.addFooterView(R.layout.head);        adapter.addFooterView(R.layout.head1);        adapter.addFooterView(R.layout.head);        //不需要分割线可不调用addItemDecoration        new RecyclerViewUtils<>(recyclerView, adapter, 1).addItemDecoration(5,R.color.colorAccent);    }    /**     * 初始化View     */    private void initView() {        recyclerView = (RecyclerView) findViewById(R.id.recyclerview);    }}

3.其他的列表实现方法均和ListView相同

例如我们想要实现HorizontalListView,我们只需要将RecyclerViewStyle设置为HorizontalListView即可。GridView和WaterFall的实现也是一样这里不再重复描述,不懂的朋友们请访问下面的Demo地址或者给我发邮件。除了ListView外的5种效果图如下。

另外由于WaterFall的Item高度是变化的,所以Item的位置无法确定,如果需要添加分割线可能会出现如下情况(屏幕最右边会显示出一条线),建议在布局内进行偏移或者添加margin。

4.备注

我的邮箱chenhuixueba@163.com

LowRecyclerView的github地址:https://github.com/liusmallpig/LowRecyclerView

LowRecyclerView的Demo地址:https://github.com/liusmallpig/TestLowRecyclerView

有关分割线的详细解析请看我的另一篇博客:http://blog.csdn.net/qq_35980424/article/details/73500829