[关闭]
@coder-pig 2015-09-23T08:09:53.000000Z 字数 4030 阅读 890

Android基础入门教程——2.4.8 ListView Item多布局的实现

Android基础入门教程


本节引言:

本节是ListView这个小节的最后一节,给大家带来的是ListView多布局Item的实现,
何为ListView Item多布局,打个比方,QQ这种聊天列表:

假如他是用一个ListView做的,那么一个ListView上不就有两种不同的Item咯!
一左一右,嘿嘿,本节就来教大家如何实现ListView的多布局!


1.要点讲解:

重写getItemViewType()方法对应View是哪个类别,以及getViewTypeCount()方法iew返回
总共多少个类别!然后再getView那里调用getItemViewType获得对应类别,再加载对应的View!


2.代码实现:

这里的话直接用上一节的两个布局,然后另外写一个Adapter重写要点中的几个几个地方:


MutiLayoutAdapter.java

  1. /**
  2. * Created by Jay on 2015/9/23 0023.
  3. */
  4. public class MutiLayoutAdapter extends BaseAdapter{
  5. //定义两个类别标志
  6. private static final int TYPE_BOOK = 0;
  7. private static final int TYPE_APP = 1;
  8. private Context mContext;
  9. private ArrayList<Object> mData = null;
  10. public MutiLayoutAdapter(Context mContext,ArrayList<Object> mData) {
  11. this.mContext = mContext;
  12. this.mData = mData;
  13. }
  14. @Override
  15. public int getCount() {
  16. return mData.size();
  17. }
  18. @Override
  19. public Object getItem(int position) {
  20. return mData.get(position);
  21. }
  22. @Override
  23. public long getItemId(int position) {
  24. return position;
  25. }
  26. //多布局的核心,通过这个判断类别
  27. @Override
  28. public int getItemViewType(int position) {
  29. if (mData.get(position) instanceof App) {
  30. return TYPE_APP;
  31. } else if (mData.get(position) instanceof Book) {
  32. return TYPE_BOOK;
  33. } else {
  34. return super.getItemViewType(position);
  35. }
  36. }
  37. //类别数目
  38. @Override
  39. public int getViewTypeCount() {
  40. return 2;
  41. }
  42. @Override
  43. public View getView(int position, View convertView, ViewGroup parent) {
  44. int type = getItemViewType(position);
  45. ViewHolder1 holder1 = null;
  46. ViewHolder2 holder2 = null;
  47. if(convertView == null){
  48. switch (type){
  49. case TYPE_APP:
  50. holder1 = new ViewHolder1();
  51. convertView = LayoutInflater.from(mContext).inflate(R.layout.item_one, parent, false);
  52. holder1.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
  53. holder1.txt_aname = (TextView) convertView.findViewById(R.id.txt_aname);
  54. convertView.setTag(R.id.Tag_APP,holder1);
  55. break;
  56. case TYPE_BOOK:
  57. holder2 = new ViewHolder2();
  58. convertView = LayoutInflater.from(mContext).inflate(R.layout.item_two, parent, false);
  59. holder2.txt_bname = (TextView) convertView.findViewById(R.id.txt_bname);
  60. holder2.txt_bauthor = (TextView) convertView.findViewById(R.id.txt_bauthor);
  61. convertView.setTag(R.id.Tag_Book,holder2);
  62. break;
  63. }
  64. }else{
  65. switch (type){
  66. case TYPE_APP:
  67. holder1 = (ViewHolder1) convertView.getTag(R.id.Tag_APP);
  68. break;
  69. case TYPE_BOOK:
  70. holder2 = (ViewHolder2) convertView.getTag(R.id.Tag_Book);
  71. break;
  72. }
  73. }
  74. Object obj = mData.get(position);
  75. //设置下控件的值
  76. switch (type){
  77. case TYPE_APP:
  78. App app = (App) obj;
  79. if(app != null){
  80. holder1.img_icon.setImageResource(app.getaIcon());
  81. holder1.txt_aname.setText(app.getaName());
  82. }
  83. break;
  84. case TYPE_BOOK:
  85. Book book = (Book) obj;
  86. if(book != null){
  87. holder2.txt_bname.setText(book.getbName());
  88. holder2.txt_bauthor.setText(book.getbAuthor());
  89. }
  90. break;
  91. }
  92. return convertView;
  93. }
  94. //两个不同的ViewHolder
  95. private static class ViewHolder1{
  96. ImageView img_icon;
  97. TextView txt_aname;
  98. }
  99. private static class ViewHolder2{
  100. TextView txt_bname;
  101. TextView txt_bauthor;
  102. }
  103. }

这里有个地方要注意的,convertView.setTag(R.id.Tag_APP,holder1);我们平时都直接
setTag(Object)的,这个是setTag的重载方法,参数是一个唯一的key以及后面的一个对象!
唯一!!!我一开始直接把TYPE_BOOK作为第一个参数,然后就报下面这个错误:

The key must be an application-specific resource id
就是前面这个要唯一,定义一个final类型的int变量和硬编码一个值的方式都是行不通的
这里的做法是直接在strings.xml中添加:

  1. <item name="Tag_APP" type="id"></item>
  2. <item name="Tag_Book" type="id"></item>

当然你也可以在res/values/下另外创建一个ids.xml文件,把上面这段代码贴上去!
除了这个还有一个要注意的地方,就是这个区分类别的标志要从0开始算,不然会报下面
这样的错误:


MainActivity.java

  1. public class MainActivity extends AppCompatActivity {
  2. private static final int TYPE_BOOK = 0;
  3. private static final int TYPE_APP = 1;
  4. private ListView list_content;
  5. private ArrayList<Object> mData = null;
  6. private MutiLayoutAdapter myAdapter = null;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. //数据准备:
  12. mData = new ArrayList<Object>();
  13. for(int i = 0;i < 20;i++){
  14. switch ((int)(Math.random() * 2)){
  15. case TYPE_BOOK:
  16. mData.add(new Book("《第一行代码》","郭霖"));
  17. break;
  18. case TYPE_APP:
  19. mData.add(new App(R.mipmap.iv_icon_baidu,"百度"));
  20. break;
  21. }
  22. }
  23. list_content = (ListView) findViewById(R.id.list_content);
  24. myAdapter = new MutiLayoutAdapter(MainActivity.this,mData);
  25. list_content.setAdapter(myAdapter);
  26. }
  27. }

上面随机生成0和1,0就往集合中添加一个Book的对象,1的话就添加一个App的对象!


3.代码下载:

ListViewDemo6.zip


本节小结:

好的,本节给大家讲解了ListView Item多布局的实现,就是两个方法的重写,
然后getView()做下判断,设置不同的布局而已~代码非常简单~
关于ListView的知识就告一段落吧,当然ListView的知识并不止这些,
异步加载,优化等等,这些我们都会在进阶部分进行学习~就说这么多,谢谢~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注