【22】Android LIstView - 多 Item 佈局

前言

我們之前使用的 ListView ,其中的 Item 都是固定的一類數據,那麼如何實現類似微信聊天界面的佈局呢?即多個類型 Item 顯示在同一個 ListView 上。

實現方法

目前想到到方法有兩個:

  • 讓每個 Item 的佈局都包含所有類型的元素然後通過隱藏的方法去組合出不同 Item 
  • 使用 Adapter 原生支持的多類型

由於方法一每次都需要 inflate 出所以類型的元素,再去隱藏,勢必會造成資源的浪費

因而本文使用的是方法二;該方法需要利用兩個函數

1)重寫 getViewTypeCount () – 該方法返回多少個不同的佈局

2)重寫 getItemViewType (int) – 根據 position 返回相應的 Item

具體實現

本文基於上一篇 打造通用 BaseAdapter,並在其基礎上,增添 多Item佈局 的內容並且整合到通用適配器及 ViewHolder 類中。

  • 更改 data 類型 List -> ArrayList
  •  將 MyAdapter2.java 傳入的數據類型由 Bean 改爲 Object,實現可複用
private ArrayList<Object> data = new ArrayList<Object>();
    public MyAdapter2(Context context, ArrayList<Object> data) {
        super(context,data);
    }
  • 去除 layoutId 變量

即 實現靈活佈局 部分不實現

    public CommonAdapter(Context context, ArrayList<T> data)
    {
        this.mContext = context;
        this.mData = data;
        //this.mLayoutId = layoutId;
        mInflater = LayoutInflater.from(context);
    }
    public MyAdapter2(Context context, ArrayList<Bean> data) {
        super(context,data);
    }
  • getView 作爲抽象函數,在 MyAdapter2.java 中實現它

爲此我們必須刪除函數convert()

    
    @Override
    public abstract  View getView(int position, View convertView, ViewGroup parent);

    //抽象方法
    //public abstract void convert(ViewHolder holder,T data);
  • MyAdapter.java
  • 增加 Book.java 及其佈局文件 item2.xml
package com.example.reusable_baseadapter;

public class Book {

    private String book_name;

    public Book(String book_name){
        this.book_name = book_name;
    }

    public String getName(){
        return book_name;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/id_listview_item2_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


</LinearLayout>
  • MyAdapter2.java 中重寫 getViewTypeCount getItemViewType
    //多佈局核心實現
    @Override
    public int getItemViewType(int position) {
        if(mData.get(position) instanceof Book)
            return type_Book;
        else if(mData.get(position) instanceof Bean)
            return type_Bean;
        else
            return super.getItemViewType(position);
    }

    @Override
    public int getViewTypeCount() {
        return item_Type_Count;
    }
  • string.xml中添加如下代碼
    <item name="Tag_Bean" type="id"/>
    <item name="Tag_Book" type="id"/>
  • 重寫 getView,實現 Item 多佈局
  • 參考網上教程寫的,代碼非常臃腫,想到我們 ViewHolder 還沒用到,忍不住想優化一下,優化結果在後文

    @Override
     public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder1 holder1 = null;
        ViewHolder2 holder2 = null;

        //獲取item視圖類型
        int type = getItemViewType(position);

        if (convertView == null)
        {
            //根據視圖類型加載
            switch (type)
            {
                case type_Bean:
                    convertView = mInflater.inflate(R.layout.activity_listview_item1,parent,false);
                    holder1 = new ViewHolder1();

                    holder1.textView = (TextView) convertView.findViewById(R.id.id_listview_item1_text);
                    holder1.imageView = (ImageView) convertView.findViewById(R.id.id_listview_item1_image);

                    convertView.setTag(R.id.Tag_Bean,holder1);
                    break;

                case type_Book:
                    convertView = mInflater.inflate(R.layout.activity_listview_item2,parent,false);
                    holder2 = new ViewHolder2();

                    holder2.textView = (TextView) convertView.findViewById(R.id.id_listview_item2_text);

                    convertView.setTag(R.id.Tag_Book,holder2);
                    break;
            }
        }
        else
        {
            switch (type)
            {
                case type_Bean:
                    holder1 = (ViewHolder1)convertView.getTag(R.id.Tag_Bean);
                    break;

                case type_Book:
                    holder2 = (ViewHolder2)convertView.getTag(R.id.Tag_Book);
                    break;
            }
        }

        //設置控件的值
        switch (type)
        {
            case type_Bean:
                Bean bean = (Bean) mData.get(position);
                holder1.textView.setText(bean.getName());
                holder1.imageView.setBackgroundResource(bean.getImageId());
                break;

            case type_Book:
                Book book = (Book)mData.get(position);
                holder2.textView.setText(book.getName());
                break;
        }

        return convertView;

    }


    private class ViewHolder1{
        ImageView imageView;
        TextView textView;
    }

    private class ViewHolder2{
        TextView textView;
    }
  • 修改 MainActivity.java 中的 InitData,爲 ListView 添加不同類型的 Item
    //修改數據初始化,加入Book類型數據
    private void initData(){
        for (int i = 1; i <= 10 ; i++){
            Bean bean = new Bean("小豆豆"+i,R.drawable.bean_image);
            Book book = new Book("Android測試指南");
            data.add(bean);
            data.add(book);
        }
    }
  • 利用 ViewHolder.java 優化 getView 函數

    //簡化getView()
    @Override
     public View getView(int position, View convertView, ViewGroup parent)
    {
        //ViewHolder1 holder1 = null;
        //ViewHolder2 holder2 = null;

        //獲取item視圖類型
        int type = getItemViewType(position);

        ViewHolder holder_one = ViewHolder.get(mContext,convertView,parent,R.layout.activity_listview_item1,position);
        ViewHolder holder_two = ViewHolder.get(mContext,convertView,parent,R.layout.activity_listview_item2,position);

        if(type == type_Bean)
        {
            Bean bean = (Bean) mData.get(position);

            TextView tv = (TextView) holder_one.getView(R.id.id_listview_item1_text);
            tv.setText(bean.getName());
            ImageView image = (ImageView) holder_one.getView(R.id.id_listview_item1_image);
            image.setBackgroundResource(bean.getImageId());

            return holder_one.getConvertView();
        }
        else if (type == type_Book)
        {
            Book book = (Book) mData.get(position);
            TextView book_tv = (TextView) holder_two.getView(R.id.id_listview_item2_text);
            book_tv.setText(book.getName());

            return holder_two.getConvertView();

        }
        else
            return convertView;
    }

效果圖

 

ps:由於是寫完以後再整理的,這裏僅展示思路和部分代碼    完整代碼見 資源信息

       如有疏漏及理解不到位的地方,還望大佬看到了能指點一二

 

 

發佈了72 篇原創文章 · 獲贊 73 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章