学习Android Material Design(RecyclerView代替ListView)
本文实例实现一下 recyclerview,代码比较简单,适合初学者,如有错误,欢迎指出。
复习 listview
可以查看这篇文章深入浅出学习android listview基础,了解关于listview 的基础知识。
实现过程中需要复写baseadapter,主要是这4个方法
- public int getcount() :适配器中数据集中 数据的个数,即listview需要显示的数据个数
- public object getitem(int position) : 获取数据集中与指定索引对应的数据项
- public long getitemid(int position) : 获取指定行对应的id
- public view getview(int position, view convertview, viewgroup parent) :获取每一个item的显示内容
一般 listview 每一项都是相同的布局,若想各个项实现不同的布局,可复写 getitemviewtype和getviewtypecount实现
recyclerview 实现
1、xml 布局
下面是recyclerview中每一项的布局 layout下面的item_article_type_1.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.cardview xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:fresco="http://schemas.android.com/apk/res-auto" android:id="@+id/cv_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:foreground="?android:attr/selectableitembackground" app:cardcornerradius="5dp" app:cardelevation="5dp" app:contentpadding="2dp"> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.facebook.drawee.view.simpledraweeview android:id="@+id/rcv_article_photo" android:layout_width="100dp" android:layout_height="100dp" android:layout_centervertical="true" fresco:actualimagescaletype="centerinside" fresco:roundascircle="true" fresco:roundingbordercolor="@color/lightslategray" fresco:roundingborderwidth="1dp" /> <linearlayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> <textview android:id="@+id/rcv_article_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_margintop="2dp" android:gravity="center" android:text="关于举办《经典音乐作品欣赏与人文审美》讲座的通知" android:textcolor="@color/primary_text" /> <!-- 新闻 发布时间 来源 阅读次数--> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="5dp" android:gravity="center" android:orientation="horizontal"> <textview android:id="@+id/rcv_article_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_marginright="2dp" android:text="2015-01-09" /> <textview android:id="@+id/rcv_article_source" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="2dp" android:layout_marginright="2dp" android:text="科学研究院" /> <textview android:id="@+id/rcv_article_readtimes" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="2dp" android:layout_marginright="2dp" android:text="1129次" /> </linearlayout> <textview android:id="@+id/rcv_article_preview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_margintop="5dp" android:ellipsize="end" android:maxlines="2" android:text="讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..." /> </linearlayout> </linearlayout> </android.support.v7.widget.cardview>
布局思路就是 cardview里面嵌入了一个linearlayout。图片部分用固定宽度100dp,文字部分利用android:layout_weight=”1”占据了其他部分。
textview利用android:gravity=”center”使得标题的文字居中。
linearlayout里面利用android:gravity=”center”使得“2015-01-09 科学研究院 1129次”居中,
新闻详情内容的textview利用
android:maxlines="2" android:ellipsize="end"
将文章内容限定为2行,超出部分用省略号显示。
使用fresco这儿有个坑需要注意,请移步这篇文章
android 之 fresco 显示圆形图片 之坑
预览效果
新闻列表的 xml 文件,layout 文件夹下面的fragment_article.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"> <android.support.v7.widget.recyclerview android:id="@+id/rcv_article" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </linearlayout>
2、adapter 实现
主要步骤是:
根据上面的 item_article_type_1.xml实现一个 class imageitemarticleviewholder extends recyclerview.viewholder
继承recyclerview.adapter ,class itemarticlelistadapter extends recyclerview.adapter <...>
重写三个方法
- public int getitemcount()
- public testadapter.imageitemarticleviewholder oncreateviewholder(viewgroup parent, int viewtype)
- public void onbindviewholder(imageitemarticleviewholder holder, int position)
public class itemarticleadapter extends recyclerview.adapter<itemarticleadapter.imageitemarticleviewholder> { //新闻列表 private list<itemarticle> articlelist; //context private context context; private layoutinflater mlayoutinflater; public itemarticleadapter(context context,list<itemarticle> articlelist) { this.context = context; this.articlelist = articlelist; mlayoutinflater = layoutinflater.from(context); } @override public itemarticleadapter.imageitemarticleviewholder oncreateviewholder(viewgroup parent, int viewtype) { view view = mlayoutinflater.inflate( r.layout.item_article_type_1, parent, false); return new imageitemarticleviewholder(view); } @override public void onbindviewholder(imageitemarticleviewholder holder, int position) { itemarticle article = articlelist.get(position); holder.rcvarticlephoto.setimageuri(uri.parse(article.getimageurl())); holder.rcvarticletitle.settext(article.gettitle()); holder.rcvarticledate.settext(article.getpublishdate()); holder.rcvarticlesource.settext(article.getsource()); //注意这个阅读次数是 int 类型,需要转化为 string 类型 holder.rcvarticlereadtimes.settext(article.getreadtimes()+"次"); holder.rcvarticlepreview.settext(article.getpreview()); } @override public int getitemcount() { return articlelist.size(); } class imageitemarticleviewholder extends recyclerview.viewholder { @injectview(r.id.rcv_article_photo) simpledraweeview rcvarticlephoto; @injectview(r.id.rcv_article_title) textview rcvarticletitle; @injectview(r.id.rcv_article_date) textview rcvarticledate; @injectview(r.id.rcv_article_source) textview rcvarticlesource; @injectview(r.id.rcv_article_readtimes) textview rcvarticlereadtimes; @injectview(r.id.rcv_article_preview) textview rcvarticlepreview; public imageitemarticleviewholder(view itemview) { super(itemview); butterknife.inject(this, itemview); } } }
3、新闻实体类 javabean
有新闻的 index,图片 url,标题,发布时间,来源,阅读次数,新闻内容预览
/** * 新闻类,这是在 recycleview 使用的新闻 javabean * 还有一个新闻详情javabean */ public class itemarticle { private int index; private string imageurl; private string title; private string publishdate; private string source; private int readtimes; private string preview; public itemarticle(int index, string imageurl, string title, string publishdate, string source, int readtimes, string preview) { this.index = index; this.imageurl = imageurl; this.title = title; this.publishdate = publishdate; this.source = source; this.readtimes = readtimes; this.preview = preview; } public int getindex() { return index; } public void setindex(int index) { this.index = index; } public string getimageurl() { return imageurl; } public void setimageurl(string imageurl) { this.imageurl = imageurl; } public string gettitle() { return title; } public void settitle(string title) { this.title = title; } public string getpublishdate() { return publishdate; } public void setpublishdate(string publishdate) { this.publishdate = publishdate; } public string getsource() { return source; } public void setsource(string source) { this.source = source; } public int getreadtimes() { return readtimes; } public void setreadtimes(int readtimes) { this.readtimes = readtimes; } public string getpreview() { return preview; } public void setpreview(string preview) { this.preview = preview; } }
4、fragment 里面使用 recyclerview
思路就是开启一个异步线程,读取多条新闻,加入list itemarticlelist,由这个itemarticlelist构造itemarticleadapter,最后利用setadapter()方法给recyclerview加上适配器。
public class articlefragment extends fragment { private static final string store_param = "param"; @injectview(r.id.rcv_article) recyclerview rcvarticle; private string mparam; //新闻列表数据 private list<itemarticle> itemarticlelist = new arraylist<itemarticle>(); //获取 fragment 依赖的 activity,方便使用 context private activity mact; public static fragment newinstance(string param) { articlefragment fragment = new articlefragment(); bundle args = new bundle(); args.putstring(store_param, param); fragment.setarguments(args); return fragment; } @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); if (getarguments() != null) { mparam = getarguments().getstring(store_param); } } @nullable @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view view = inflater.inflate(r.layout.fragment_article, null); log.i(store_param, "in storefragment"); mact = getactivity(); butterknife.inject(this, view); return view; } @override public void onactivitycreated(@nullable bundle savedinstancestate) { super.onactivitycreated(savedinstancestate); rcvarticle.setlayoutmanager(new linearlayoutmanager(mact));//这里用线性显示 类似于listview // rcvarticle.setlayoutmanager(new gridlayoutmanager(mact, 2));//这里用线性宫格显示 类似于grid view // rcvarticle.setlayoutmanager(new staggeredgridlayoutmanager(2, orientationhelper.vertical));//这里用线性宫格显示 类似于瀑布流 new latestarticletask().execute(); } @override public void ondestroyview() { super.ondestroyview(); butterknife.reset(this); } class latestarticletask extends asynctask<string, void, list<itemarticle>> { @override protected void onpreexecute() { super.onpreexecute(); } @override protected list<itemarticle> doinbackground(string... params) { itemarticle storeinfo1 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticle storeinfo2 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticle storeinfo3 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticle storeinfo4 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticle storeinfo5 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticle storeinfo6 = new itemarticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/u5912p28t3d3634984f328dt20120520152700.jpg", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129, "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..."); itemarticlelist.add(storeinfo1); itemarticlelist.add(storeinfo2); itemarticlelist.add(storeinfo3); itemarticlelist.add(storeinfo4); itemarticlelist.add(storeinfo5); itemarticlelist.add(storeinfo6); return itemarticlelist; } @override protected void onpostexecute(list<itemarticle> data) { super.onpostexecute(data); itemarticleadapter adapter = new itemarticleadapter(mact, data); rcvarticle.setadapter(adapter); } } }
效果图
利用修改布局,线性显示或者宫格显示。(以前宫格显示很麻烦,现在一条命令就好了,google 搞得这么简单,我们android 工程师要失业的好伐?!!)
rcvarticle.setlayoutmanager(new linearlayoutmanager(mact));//这里用线性显示 类似于listview // rcvarticle.setlayoutmanager(new gridlayoutmanager(mact, 2));//这里用线性宫格显示 类似于grid view // rcvarticle.setlayoutmanager(new staggeredgridlayoutmanager(2, orientationhelper.vertical));//这里用线性宫格显示 类似于瀑布流
知识点
textview需要有settext(int resid) 方法,但是这儿 int 表示 resourceid,如果我想把阅读次数(int 1123)赋给这个 textview,不能使用这个方法。
需要把 int 转化为 string
int 转 string 有三种方法 int i =8; string s =integer.tostring(i); string g =string.valueof(i); string h =i+""; holder.rcvarticlereadtimes.settext(string.valueof(article.getreadtimes()));
总结 todo list
- picasso 图片缓存库的学习
- 实现 recyclerview 每个项各自的布局
遇到的坑
rcvarticle.setlayoutmanager()需要在onactivitycreated()方法里调用,如果在oncreateview()调用会抛出空指针异常。
public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view view = inflater.inflate(r.layout.fragment_one_latest, container, false); mact = getactivity(); //错误,需要在onactivitycreated里面调用 rcvarticle.setlayoutmanager(new linearlayoutmanager(mact));//这里用线性显示 类似于listview butterknife.inject(this, view); return view; }
java.lang.nullpointerexception
at com.example.administrator.seenews.ui.fragment.common.articlefragment.oncreateview(articlefragment.java:111)
以上就是本文的全部内容,希望对大家的学习有所帮助。
上一篇: 自定义时间格式转换代码分享
推荐阅读
-
学习Android Material Design(RecyclerView代替ListView)
-
学习Android Material Design(RecyclerView代替ListView)
-
学习使用Material Design控件(四)Android实现标题栏自动缩放、放大效果
-
学习使用Material Design控件(四)Android实现标题栏自动缩放、放大效果
-
android Material Design 学习之六:AppBarLayout
-
Android Study Material Design 二 之:这可能是RecyclerView最全解析 初级使用(一)
-
Android Study Material Design 六 之:TextInputLayout学习及分析部分源码