学习Android Material Design(RecyclerView代替ListView)

时间:2021-09-01 05:42:28

本文实例实现一下 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 显示圆形图片 之坑

预览效果

学习Android Material Design(RecyclerView代替ListView)

新闻列表的 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));//这里用线性宫格显示 类似于瀑布流

学习Android Material Design(RecyclerView代替ListView)

学习Android Material Design(RecyclerView代替ListView)

知识点

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)

以上就是本文的全部内容,希望对大家的学习有所帮助。