本文实例实现一下 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<?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利用
1
2
|
android:maxlines= "2" android:ellipsize= "end" |
将文章内容限定为2行,超出部分用省略号显示。
使用fresco这儿有个坑需要注意,请移步这篇文章
android 之 fresco 显示圆形图片 之坑
预览效果
新闻列表的 xml 文件,layout 文件夹下面的fragment_article.xml
1
2
3
4
5
6
7
8
9
10
11
12
|
<?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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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,标题,发布时间,来源,阅读次数,新闻内容预览
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/** * 新闻类,这是在 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加上适配器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
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 工程师要失业的好伐?!!)
1
2
3
|
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
1
2
3
4
5
6
|
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()调用会抛出空指针异常。
1
2
3
4
5
6
7
8
9
|
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)
以上就是本文的全部内容,希望对大家的学习有所帮助。