【问题标题】:Add a list item that is different than the rest of a list添加与列表其余部分不同的列表项
【发布时间】:2015-08-04 18:09:53
【问题描述】:

我有一个自定义列表适配器。适配器由 List<CustomObject> itemsOfList
备份 工作正常。
我有时需要显示一个列表项,它的布局与列表中的其余项目完全不同,实际上只是文本(就像列表中某处的“标题”)。
我做了以下方法。
在我的适配器的getView 实现中,如果作为参数传递的position 是例如7 然后我返回我的自定义视图。
除了以下小问题外,这也可以正常工作:
我从列表中跳过了一个项目。
在我的getView 代码中:

CustomObject o = itemsOfList.get(position);  

填充我列表中的项目。
但是当getView 以位置7 被调用时,我返回了我的自定义视图。然后下一个电话是位置 8 但这意味着我从不这样做:

CustomObject o = itemsOfList.get(7);  

我该如何解决这个问题?

【问题讨论】:

  • 我不明白 - 我认为您忽略了添加一条信息来连接这些点。根据您的描述,完全不清楚 7 的动机是什么,即为什么您的适配器返回您的自定义视图以响应项目列表中的 index - 在我看来,只有对 index 采取行动才有意义i>值项,不在索引上。
  • @Durandal:我想在第 7 位添加类似标题/横幅的内容
  • 所以本质上你将模型的一部分(标题应出现的索引)放入适配器中?那是错误的设计-您应该将一个特殊值放入列表中,并让适配器对该特殊值进行操作-问题就消失了。
  • @Durandal:我不确定我是否理解您的建议。您能否通过一个小示例将其发布为答案和替代方法?

标签: java android android-fragments android-listview android-adapter


【解决方案1】:

所有列表都是从零开始的。试试CustomObject o = itemsOfList.get(position-1);

【讨论】:

    【解决方案2】:

    如果您使用的是列表,那么在 java 中,在使用上述对象的 get() 方法时,List、Arraylist 和 Map Object 类型都是从零开始的。如果您想获得列表中的第一项,则如下所示:

    ArrayList list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    String str = (String) list.get(0); //This gets the item named 1
    

    你正在做的事情是这样的:

    String str = (String) list.get(1); //This gets the item named 2
    

    但您希望它返回名为 1 的项目,因此正确的方法是使用位置 - 1 来获取您想要的项目。

    【讨论】:

      【解决方案3】:

      需要在视图中显示的每个元素都有一个项目,以保持模型中的项目与显示的视图之间的一对一关系。这可以通过让适配器谎言了解项目的数量来完成(这可能会变得复杂),或者只是有一个代表你的标题的特殊项目。

      后者可以这样做:

      // where the items are populated:
      for (whatever) {
          itemsOfList.add(new CustomObject("item"));
      }
      // now add items for the header(s) to be displayed
      itemsOfList.insert(headerIndex, new CustomObject("header"));
      

      您可以拥有 CustomObject 的特殊子类(例如 CustomHeaderObject),也可以只是 CustomObject 中的类型标志。让我们假设后者:

      class CustomObject {
          String type;
          // other data members
      
          public CustomObject(String type) {
              this.type = type;
          }
      
          public boolean isHeader() {
              return "header".equals(type);
          }
      }
      

      这可以通过常量、枚举等变得更漂亮。重要的是 CustomObject 有一种方法可以告诉它需要如何显示

       public View getView (int position, View convertView, ViewGroup parent) {
            CustomObject item = itemsOfList.get(position);
            if (item.isHeader()) {
                return new HeaderView(...);
            } else {
                return new ItemView(...);
            }
       }
      

      getView() 方法根据项目类型选择它生成的视图类型。


      替代方法是虚拟地通过更改适配器中与项目检索相关的所有方法将项目添加到 listOfItems。适配器需要实现从适配器项计数/索引到标题项的映射,例如在adapter中有两组数据,item和headers:

       listOfItems[Item1, Item2, Item3]
       headerIndex = 1
      

      适配器暴露的是两者的混合:

       getView() [Item1, header, Item2, Item3]
      

      例如,适配器中的 getItem() 方法需要做:

       public Object getItem (int position) {
           if (position < headerIndex) {
                // items before header are adressed normally
                return listOfItems(position);
           } else if (position == headerIndex) {
                // smuggles the header in
               return "header";
           } else {
                // items after header are adressed as position minus one
                return listOfItems(position - 1);
           }
      }
      
      public int getCount() {
           // there are as many items as in the list PLUS one header 
           return listOfItems.size() + 1;
      }
      
      // similar mapping for all other methods that address items/count/view
      

      正如您所见,使用 ONE 标头已经很复杂了,如果有多个标头,情况会变得更糟。

      【讨论】:

      • 我喜欢你提出的这种方法。我目前正在做你描述的后者,即为position 使用“技巧”。有趣的是,虽然我的方法似乎有效,但我没有在 getCount 中添加 +1
      • 我遇到的另一个问题是getView 中传递的视图基本上被重用了,所以我也必须考虑到这一点
      【解决方案4】:

      Itens 从 0 索引开始。所以第一个是itemsOfList.get(0),最后一个是itemsOfList.get(itemsOfList.size())。 建议使用Iterator 来迭代Collection。您也可以使用增强的 for 循环。 请记住,List 接口没有迭代顺序。

      【讨论】:

        【解决方案5】:

        还有一些其他方法需要注意(getCountgetItemgetItemId)。

        但是,如果您的特殊位置(索引 6)更改/未始终确定,这可能会非常难以扩展。或者如果有更多的特殊情况。我倾向于在适配器 (mAdapterList) 中构造一个不属于 CustomObject 的项目列表,但其中包含特殊情况项目,因此三个 get* 方法不必考虑任何特殊情况.

        不过,根据你的意图,我会这样做:

        public class MyListAdapter extends BaseAdapter
        {
            List<CustomObject> mAdapterList;
            Context mContext;
        
            public MyListAdapter(Context context, List<CustomObject> items)
            {
                mContext = context;
                mAdapterList = items != null ? items : new ArrayList<CustomObject>();
            }
        
            @Override
            public int getCount()
            {
                return mAdapterList.size() + 1;
            }
        
            @Override
            public Object getItem(int position)
            {
                if (position < 6)
                    return mAdapterList.get(position);
                else if (position > 6)
                    return mAdapterList.get(position - 1);
                else
                    return null;
            }
        
            @Override
            public long getItemId(int position)
            {
                if (position < 6)
                    return position;
                else if (position > 6)
                    return position - 1;
                else
                    return -1;
            }
        
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (position != 6)
                {
                    RegularItemViewHolder viewHolder;
                    if (convertView == null || convertView.getTag() instanceof SpecialItemViewHolder)
                    {
                        convertView = LayoutInflater.from(mContext).inflate(R.layout.regular_item, parent, false);
                        int arrayPos = (position < 6) ? position : position - 1;
                        viewHolder = new RegularItemViewHolder();
                        viewHolder.mRegularTextView = (TextView)convertView.findViewById(R.id.reg_textview);
                        convertView.setTag(viewHolder);
                    }
                    else
                    {
                        viewHolder = (RegularItemViewHolder)convertView.getTag();
                    }
                    viewHolder.mRegularTextView.setText(mAdapterList.get((position < 6 ? position : position - 1)).mText);
                }
                else
                {
                    SpecialItemViewHolder viewHolder;
                    if (convertView == null || convertView.getTag() instanceof RegularItemViewHolder)
                    {
                        convertView = LayoutInflater.from(mContext).inflate(R.layout.special_item, parent, false);
                        viewHolder = new SpecialItemViewHolder();
                        viewHolder.mSpecialTextView = (TextView)convertView.findViewById(R.id.special_textview);
                        convertView.setTag(viewHolder);
                    }
                    else
                    {
                        viewHolder = (SpecialItemViewHolder)convertView.getTag();
                    }
                    viewHolder.mSpecialTextView.setText("My special text");
                }
        
                return convertView;
            }
        
            public static class CustomObject
            {
                public CustomObject(String text)
                {
                    mText = text;
                }
                public String mText;
            }
        
            private class RegularItemViewHolder
            {
                public TextView mRegularTextView;
            }
        
            private class SpecialItemViewHolder
            {
                public TextView mSpecialTextView;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-11-10
          • 1970-01-01
          • 1970-01-01
          • 2021-05-27
          • 1970-01-01
          • 2018-03-08
          • 1970-01-01
          • 2021-12-11
          相关资源
          最近更新 更多