为具有不同项目布局的 ListView 创建 ViewHolder [英] Creating ViewHolders for ListViews with different item layouts

查看:28
本文介绍了为具有不同项目布局的 ListView 创建 ViewHolder的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个针对不同项目具有不同布局的 ListView.有些项目是分隔符.有些项目是不同的,因为它们包含不同类型的数据等.

I have a ListView with different layouts for different items. Some items are separators. Some items are different because they hold different kinds of data, etc.

我想实现 ViewHolders 来加速 getView 过程,但我不太确定如何去做.不同的布局有不同的数据片段(这使得命名变得困难)和不同数量的我想要使用的视图.

I want to implement ViewHolders to speed up the getView process, but I'm not quite sure how to go about it. Different layouts have different pieces of data (which makes naming difficult) and different numbers of Views I want to use.

我应该怎么做?

我能想到的最好的主意是创建一个带有 X 个项目的通用 ViewHolder,其中 X 是项目布局中视图数量最多的视图数量.对于具有少量视图的其他视图,我将只使用 ViewHolder 中这些变量的一部分.所以说我有 2 个布局用于 2 个不同的项目.一个有 3 个 TextViews,另一个有 1 个.我会用 3 个 TextView 变量创建一个 ViewHolder,并且只将其中的 1 个用于我的其他项目.我的问题是这可能会变得非常难看,而且感觉非常糟糕;特别是当一个项目布局可能有许多不同类型的视图时.

The best idea I can come up with is to create a generic ViewHolder with X items where X is the number of Views in an item layout with the highest number of them. For the other views with a small number of Views, I'll just use a subsection of those variables in the ViewHolder. So say I have 2 layouts I use for 2 different items. One has 3 TextViews and the other has 1. I would create a ViewHolder with 3 TextView variables and only use 1 of them for my other item. My problem is that this can get really ugly looking and feels really hacky; especially when an item layout may have many Views of many different types.

这是一个非常基本的 getView:

Here is a very basic getView:

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

    MyHolder holder;

    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.layout_mylistlist_item, parent, false);

        holder = new MyHolder();
        holder.text = (TextView) v.findViewById(R.id.mylist_itemname);
        v.setTag(holder);
    }
    else {
        holder = (MyHolder)v.getTag();
    }

    MyListItem myItem = m_items.get(position);

    // set up the list item
    if (myItem != null) {
        // set item text
        if (holder.text != null) {
            holder.text.setText(myItem.getItemName());
        }
    }

    // return the created view
    return v;
}

假设我有不同类型的行布局,我可以为每种类型的行设置一个 ViewHolder.但是我会声明什么类型的持有人"在顶部?或者我会为每种类型声明一个持有者,然后将一个用于我所在行的类型.

Suppose I had different types of row layouts, I could have a ViewHolder for each type of row. But what type would I declare "holder" to be at the top? Or would I declare a holder for each type and then use the one for the type of row I'm on.

推荐答案

ListView 有一个内置的类型管理系统.在您的适配器中,您有多种类型的项目,每个项目都有自己的视图和布局.通过覆盖 getItemViewType 来返回给定位置,ListView 需要为该类型的数据传递正确的转换视图.然后,在您的 getView 方法中,只需检查数据类型并使用 switch 语句以不同方式处理每种类型.

ListView has a built in type management system. In your adapter, you have several types of items, each with their own view and layout. By overriding getItemViewType to return the data type of a given position, ListView is garunteed to pass in the correct convertview for that type of data. Then, in your getView method simply check the datatype and use a switch statement to handle each type differently.

为了命名清晰和易于维护,每个布局类型都应该有自己的视图.将 ViewHolders 命名为与每种数据类型相关的名称,以保持一切正常.

Each Layout type should have its own viewholder for naming clarity and ease of maintainence. Name the ViewHolders something related to each data type to keep everything straight.

试图将所有内容重叠到一个 ViewHolder 中是不值得的.

Trying to overlap everything into one ViewHolder is just not worth the effort.

编辑示例

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    int viewType = this.getItemViewType(position);

    switch(viewType)
    {
       case TYPE1:

        Type1Holder holder1; 

         View v = convertView; 
         if (v == null) { 
             LayoutInflater vi = (LayoutInflater)getContext().getSystemService     (Context.LAYOUT_INFLATER_SERVICE); 
             v = vi.inflate(R.layout.layout_mylistlist_item_type_1, parent, false); 

             holder1 = new Type1Holder (); 
             holder1.text = (TextView) v.findViewById(R.id.mylist_itemname); 
             v.setTag(holder1); 
         } 
         else { 
             holder1 = (Type1Holder)v.getTag(); 
         } 

         MyListItem myItem = m_items.get(position); 

         // set up the list item 
         if (myItem != null) { 
             // set item text 
             if (holder1.text != null) { 
                 holder1.text.setText(myItem.getItemName()); 
             } 
         } 

         // return the created view 
         return v; 


     case TYPE2:
            Type2Holder holder2; 

         View v = convertView; 
         if (v == null) { 
             LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
             v = vi.inflate(R.layout.layout_mylistlist_item_type_2, parent, false); 

             holder2 = new Type2Holder (); 
             holder2.text = (TextView) v.findViewById(R.id.mylist_itemname); 
             holder2.icon = (ImageView) v.findViewById(R.id.mylist_itemicon); 
             v.setTag(holder1); 
         } 
         else { 
             holder2 = (Type2Holder)v.getTag(); 
         } 

         MyListItem myItem = m_items.get(position); 

         // set up the list item 
         if (myItem != null) { 
             // set item text 
             if (holder2.text != null) { 
                 holder2.text.setText(myItem.getItemName()); 
             } 

             if(holder2.icon != null)
                 holder2.icon.setDrawable(R.drawable.icon1);
         } 


         // return the created view 
         return v; 


       default:
           //Throw exception, unknown data type
    }
} 

这篇关于为具有不同项目布局的 ListView 创建 ViewHolder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆