Android RecycleView多种布局实现(工厂模式)
程序员文章站
2022-03-11 08:40:39
RecycleView是个很常用的控件,很多APP中都可以看到它的身影,同时它也是个很难用的控件,主要就难在多种布局的实现。 在《第一行代码—Android》这本书里边有个RecycleView实现的聊天界面布局,左右两种布局写在了同一个文件中,如果是发送来的消息,就隐藏右侧布局,反之隐藏左侧布局, ......
recycleview是个很常用的控件,很多app中都可以看到它的身影,同时它也是个很难用的控件,主要就难在多种布局的实现。
在《第一行代码—android》这本书里边有个recycleview实现的聊天界面布局,左右两种布局写在了同一个文件中,如果是发送来的消息,就隐藏右侧布局,反之隐藏左侧布局,这种方式对于比较简单的、只有两种item的界面是可行的,假如我们的item有多种布局,那么这种方式就显得很笨重。对于多种布局,我们可以使用工厂模式来实现。
1.首先看看效果(gif一直上传失败,只好传jpg了):
这里的layoutmanager使用gridlayoutmanager,设置为6列,然后在adapter类中根据不同的类型来设置所占列数,具体见adapter类的setspancount方法。
2.然后是类图:
3.adapter类:
适配器的代码很短,设置数据和绑定view的代码都写在了itemholder的子类里面;
list<item>储存三种类型的item数据,如果需要增加新的类型,只要实现item接口就可以了;
在onbindviewholder方法中调用itemholder的setdata()方法来设置数据;
1 public class multilistadapter extends recyclerview.adapter<itemholder> { 2 3 private list<item> mdatalist; 4 5 public multilistadapter(list<item> datalist) { 6 mdatalist = datalist; 7 } 8 9 @nonnull 10 @override 11 public itemholder oncreateviewholder(@nonnull viewgroup viewgroup, int type) { 12 return itemholderfactory.getitemholder(viewgroup, type); 13 } 14 15 @override 16 public void onbindviewholder(@nonnull itemholder viewholder, int i) { 17 //设置 holder 数据 18 viewholder.setdata(mdatalist.get(i)); 19 } 20 21 @override 22 public int getitemviewtype(int position) { 23 return mdatalist.get(position).gettype(); 24 } 25 26 @override 27 public int getitemcount() { 28 return mdatalist.size(); 29 } 30 31 public void setspancount(gridlayoutmanager layoutmanager) { 32 layoutmanager.setspansizelookup(new gridlayoutmanager.spansizelookup() { 33 @override 34 public int getspansize(int i) { 35 int type = getitemviewtype(i); 36 switch (type) { 37 default: 38 case itemholderfactory.item_large: 39 return 3; 40 case itemholderfactory.item_small: 41 return 2; 42 case itemholderfactory.item_title_bar: 43 return 6; 44 } 45 } 46 }); 47 } 48 }
4.itemholder抽象类:
setdata方法用来设置item布局的数据
1 public abstract class itemholder extends recyclerview.viewholder { 2 public itemholder(view item) { 3 super(item); 4 } 5 6 public abstract void setdata(item itemdata); 7 }
5.largeitemholder类:
另外两个类似
1 public class largeitemholder extends itemholder { 2 3 private imageview mitemimage; 4 private textview mtitle; 5 private textview msubtitle; 6 7 public largeitemholder(view item) { 8 super(item); 9 mitemimage = item.findviewbyid(r.id.item_image); 10 mtitle = item.findviewbyid(r.id.item_title); 11 msubtitle = item.findviewbyid(r.id.item_sub_title); 12 } 13 14 @override 15 public void setdata(item itemdata) { 16 itemlarge item = (itemlarge) itemdata; 17 mitemimage.setimagebitmap(item.getimage()); 18 mtitle.settext(item.gettitle()); 19 msubtitle.settext(item.getsubtitle()); 20 } 21 }
6.item接口:
1 public interface item { 2 int gettype(); 3 }
7.itemlarge类(一个图片、一个标题和一个副标题):
另外两个类似
1 public class itemlarge implements item { 2 3 private bitmap mimage; 4 private string mtitle; 5 private string msubtitle; 6 7 public itemlarge(bitmap bitmap, string title, string subtitle) { 8 mimage = bitmap; 9 mtitle = title; 10 msubtitle = subtitle; 11 } 12 13 public bitmap getimage() { 14 return mimage; 15 } 16 17 public string gettitle() { 18 return mtitle; 19 } 20 21 public string getsubtitle() { 22 return msubtitle; 23 } 24 25 @override 26 public int gettype() { 27 return itemholderfactory.item_large; 28 } 29 }
8.工厂类itemholderfactory:
三个常量表示不同的布局类型,通过getitemholder来创建viewholder。
1 public class itemholderfactory { 2 3 public static final int item_large = 0; 4 public static final int item_small = 1; 5 public static final int item_title_bar = 2; 6 7 @intdef({ 8 item_large, 9 item_small, 10 item_title_bar 11 }) 12 @interface itemtype {} 13 14 static itemholder getitemholder(viewgroup parent, @itemtype int type) { 15 switch (type) { 16 default: 17 case item_large: 18 return new largeitemholder(layoutinflater 19 .from(parent.getcontext()).inflate(r.layout.item_large, parent, false)); 20 case item_small: 21 return new smallitemholder(layoutinflater 22 .from(parent.getcontext()).inflate(r.layout.item_small, parent, false)); 23 case item_title_bar: 24 return new titlebaritemholder(layoutinflater 25 .from(parent.getcontext()).inflate(r.layout.item_title_bar, parent, false)); 26 } 27 } 28 }
9.listactivity类:
1 public class listactivity extends appcompatactivity { 2 3 list<item> itemlist = new arraylist<>(); 4 5 @override 6 protected void oncreate(bundle savedinstancestate) { 7 super.oncreate(savedinstancestate); 8 setcontentview(r.layout.activity_list); 9 10 initdata(); 11 12 gridlayoutmanager layoutmanager = new gridlayoutmanager(this, 6); 13 multilistadapter adapter = new multilistadapter(itemlist); 14 adapter.setspancount(layoutmanager); 15 16 recyclerview recyclerview = findviewbyid(r.id.recycle_view); 17 recyclerview.setlayoutmanager(layoutmanager); 18 recyclerview.setadapter(adapter); 19 } 20 21 private void initdata() { 22 //添加数据 23 itemlist.add(new itemtitlebar("hot new", null)); 24 itemlist.add(new itemlarge( 25 bitmapfactory.decoderesource(getresources(), r.drawable.img_1), 26 "one more light", 27 "linkin park")); 28 itemlist.add(new itemlarge( 29 bitmapfactory.decoderesource(getresources(), r.drawable.img_2), 30 "let go ", 31 "avril lavigne")); 32 itemlist.add(new itemtitlebar("recommended", null)); 33 itemlist.add(new itemsmall( 34 bitmapfactory.decoderesource(getresources(), r.drawable.img_3), 35 "bridge to terabithia")); 36 itemlist.add(new itemsmall( 37 bitmapfactory.decoderesource(getresources(), r.drawable.img_4), 38 "life is beautiful")); 39 itemlist.add(new itemsmall( 40 bitmapfactory.decoderesource(getresources(), r.drawable.img_5), 41 "a violent flame")); 42 itemlist.add(new itemtitlebar("top rated", null)); 43 itemlist.add(new itemlarge( 44 bitmapfactory.decoderesource(getresources(), r.drawable.img_6), 45 "furious 7: original motion picture soundtrack", 46 "various artists")); 47 itemlist.add(new itemlarge( 48 bitmapfactory.decoderesource(getresources(), r.drawable.img_7), 49 "halo 5: guardians (original soundtrack)", 50 "kazuma jinnouchi")); 51 } 52 }
10.布局文件(item_large.xml):
layout_width用match_parent是为了item在网格中居中,此处match_parent相当于宽度为item所占的列数。
1 <?xml version="1.0" encoding="utf-8"?> 2 <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:orientation="vertical" 5 android:layout_width="match_parent" 6 android:layout_height="wrap_content" 7 android:layout_margin="4dp" 8 android:background="#ffffff" 9 android:elevation="2dp"> 10 11 <imageview 12 android:contentdescription="@id/item_title" 13 android:id="@+id/item_image" 14 android:layout_width="match_parent" 15 android:layout_height="170dp" 16 android:scaletype="centercrop" 17 tools:src="@drawable/img_7" /> 18 19 <textview 20 android:id="@+id/item_title" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:layout_margintop="8dp" 24 android:paddingstart="8dp" 25 android:paddingend="8dp" 26 android:lines="1" 27 android:ellipsize="end" 28 android:textcolor="#000000" 29 android:textsize="18sp" 30 tools:text="item title" /> 31 32 <textview 33 android:id="@+id/item_sub_title" 34 android:layout_width="match_parent" 35 android:layout_height="wrap_content" 36 android:layout_marginbottom="8dp" 37 android:paddingstart="8dp" 38 android:paddingend="8dp" 39 android:lines="1" 40 android:ellipsize="end" 41 android:textsize="14sp" 42 tools:text="sub title" /> 43 44 </linearlayout>
上一篇: 房价信息爬取