尊重原创,转载注明: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和RecyclerViewStytle更详细的解释请移步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