【问题标题】:android attaching multiple adapters to one adapterandroid将多个适配器附加到一个适配器
【发布时间】:2011-12-19 08:08:49
【问题描述】:

我一直在使用SeparatedListAdapter,它非常有名并且运行良好,但似乎我无法使用 addSection() 添加 SimpleAdapter,因为应用程序已终止。我正在提供一些代码来向您展示我正在尝试做什么并获得一些指导以解决此问题。如果您需要任何其他代码或任何东西,请告诉我:

// Declarations

private SimpleAdapter _resultsAdapter;
private ArrayAdapter<String> _adapter;
private List<Map<String,?>> _resultsList;
private ArrayList<String> _stringList = new ArrayList<String>();

// Much of source code here

// The following lines work (I can addSection()).
    _adapter =  new ArrayAdapter<String>(this, R.layout.custom_list_item, _stringList);
    _sla = new SeparatedListAdapter(this);
    _sla.addSection("Input Data", _adapter);  

// More source code here...

// The following causes a crash
_resultsList.add(createItem(resultTitle.toString(), fieldDetails.toString())); // Loading data in a loop (works 100%)
_resultsAdapter = new SimpleAdapter(CompanyInfoServiceViewActivity.this, _resultsList, R.layout.list_complex, new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption });
_sla.addSection("Results", _resultsAdapter); // Crashes here. _sla is not null (see above)

【问题讨论】:

    标签: android listview adapter


    【解决方案1】:

    您可以将 MergeAdapter 用于您的 ListView。这是我经过修改和全面测试的版本。

    /**
    * Adapter that merges multiple child adapters and views into a single
    * contiguous whole.
    * 
    * Adapters used as pieces within MergeAdapter must have view type IDs
    * monotonically increasing from 0. Ideally, adapters also have distinct ranges
    * for their row ids, as returned by getItemId().
    * 
    */
    public class MergeAdapter extends BaseAdapter implements SectionIndexer {
        protected ArrayList<ListAdapter> pieces = new ArrayList<ListAdapter>();
        protected String noItemsText;
    
        /**
        * Stock constructor, simply chaining to the superclass.
        */
        public MergeAdapter() {
            super();
        }
    
        /**
        * Adds a new adapter to the roster of things to appear in the aggregate
        * list.
        * 
        * @param adapter
        *            Source for row views for this section
        */
        public void addAdapter(ListAdapter adapter) {
            pieces.add(adapter);
            adapter.registerDataSetObserver(new CascadeDataSetObserver());
        }
    
        /**
        * Get the data item associated with the specified position in the data set.
        * 
        * @param position
        *            Position of the item whose data we want
        */
        public Object getItem(int position) {
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    return (piece.getItem(position));
                }
    
                position -= size;
            }
    
            return (null);
        }
    
        public void setNoItemsText(String text){
            noItemsText = text;
        }
    
        /**
        * Get the adapter associated with the specified position in the data set.
        * 
        * @param position
        *            Position of the item whose adapter we want
        */
        public ListAdapter getAdapter(int position) {
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    return (piece);
                }
    
                position -= size;
            }
    
            return (null);
        }
    
        /**
        * How many items are in the data set represented by this Adapter.
        */
        public int getCount() {
            int total = 0;
    
            for (ListAdapter piece : pieces) {
                total += piece.getCount();
            }
    
            if(total == 0 && noItemsText != null){
                total = 1;
            }
    
            return (total);
        }
    
        /**
        * Returns the number of types of Views that will be created by getView().
        */
        @Override
        public int getViewTypeCount() {
            int total = 0;
    
            for (ListAdapter piece : pieces) {
                total += piece.getViewTypeCount();
            }
    
            return (Math.max(total, 1)); // needed for setListAdapter() before
                                            // content add'
        }
    
        /**
        * Get the type of View that will be created by getView() for the specified
        * item.
        * 
        * @param position
        *            Position of the item whose data we want
        */
        @Override
        public int getItemViewType(int position) {
            int typeOffset = 0;
            int result = -1;
    
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    result = typeOffset + piece.getItemViewType(position);
                    break;
                }
    
                position -= size;
                typeOffset += piece.getViewTypeCount();
            }
    
            return (result);
        }
    
        /**
        * Are all items in this ListAdapter enabled? If yes it means all items are
        * selectable and clickable.
        */
        @Override
        public boolean areAllItemsEnabled() {
            return (false);
        }
    
        /**
        * Returns true if the item at the specified position is not a separator.
        * 
        * @param position
        *            Position of the item whose data we want
        */
        @Override
        public boolean isEnabled(int position) {
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    return (piece.isEnabled(position));
                }
    
                position -= size;
            }
    
            return (false);
        }
    
        /**
        * Get a View that displays the data at the specified position in the data
        * set.
        * 
        * @param position
        *            Position of the item whose data we want
        * @param convertView
        *            View to recycle, if not null
        * @param parent
        *            ViewGroup containing the returned View
        */
        public View getView(int position, View convertView, ViewGroup parent) {
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
    
                    return (piece.getView(position, convertView, parent));
                }
    
                position -= size;
            }
    
            if(noItemsText != null){
                TextView text = new TextView(parent.getContext());
                text.setText(noItemsText);
                return text;
            }
    
            return (null);
        }
    
        /**
        * Get the row id associated with the specified position in the list.
        * 
        * @param position
        *            Position of the item whose data we want
        */
        public long getItemId(int position) {
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    return (piece.getItemId(position));
                }
    
                position -= size;
            }
    
            return (-1);
        }
    
        public int getPositionForSection(int section) {
            int position = 0;
    
            for (ListAdapter piece : pieces) {
                if (piece instanceof SectionIndexer) {
                    Object[] sections = ((SectionIndexer) piece).getSections();
                    int numSections = 0;
    
                    if (sections != null) {
                        numSections = sections.length;
                    }
    
                    if (section < numSections) {
                        return (position + ((SectionIndexer) piece)
                                .getPositionForSection(section));
                    } else if (sections != null) {
                        section -= numSections;
                    }
                }
    
                position += piece.getCount();
            }
    
            return (0);
        }
    
        public int getSectionForPosition(int position) {
            int section = 0;
    
            for (ListAdapter piece : pieces) {
                int size = piece.getCount();
    
                if (position < size) {
                    if (piece instanceof SectionIndexer) {
                        return (section + ((SectionIndexer) piece)
                                .getSectionForPosition(position));
                    }
    
                    return (0);
                } else {
                    if (piece instanceof SectionIndexer) {
                        Object[] sections = ((SectionIndexer) piece).getSections();
    
                        if (sections != null) {
                            section += sections.length;
                        }
                    }
                }
    
                position -= size;
            }
    
            return (0);
        }
    
        public Object[] getSections() {
            ArrayList<Object> sections = new ArrayList<Object>();
    
            for (ListAdapter piece : pieces) {
                if (piece instanceof SectionIndexer) {
                    Object[] curSections = ((SectionIndexer) piece).getSections();
    
                    if (curSections != null) {
                        for (Object section : curSections) {
                            sections.add(section);
                        }
                    }
                }
            }
    
            if (sections.size() == 0) {
                return (null);
            }
    
            return (sections.toArray(new Object[0]));
        }
    
        private class CascadeDataSetObserver extends DataSetObserver {
            @Override
            public void onChanged() {
                notifyDataSetChanged();
            }
    
            @Override
            public void onInvalidated() {
                notifyDataSetInvalidated();
            }
        }
    }
    

    如果需要,您还需要 ListTitleAdapter 在每个适配器之前放置一些标题。

      public class ListTitleAdapter extends BaseAdapter {
    
          Context context;
          String text;
          BaseAdapter parentAdapter;
    
          public ListTitleAdapter(Context c, String textToShow) {
              this(c, textToShow, null);
      }
    
          public ListTitleAdapter(Context c, String textToShow, BaseAdapter dependentAdapter) {
          super();
          context = c;
          text = textToShow;
    
          if(dependentAdapter != null){
              parentAdapter = dependentAdapter;
          }
      }
    
          public int getCount() {
          if(parentAdapter != null){
              if(parentAdapter.getCount() == 0){
                  return 0;
              }
          }
          return 1;
      }
    
          public Object getItem(int position) {
          return position;
      }
    
          public long getItemId(int position) {
          return position;
      }
    
          public View getView(int position, View convertView, ViewGroup parent) {
          LinearLayout layout = new LinearLayout(context);
          TextView textView = new TextView(context);
          textView.setText(text);
    
          layout.addView(textView);
    
          return layout;
      }
      }
    

    这里是关于如何使用这两个类的小例子。

    MergeAdapter mergeAdapter = new MergeAdapter();
    
    mergeAdapter.addAdapter(new ListTitleAdapter(context, "Title1", someAdapter1));
    mergeAdapter.addAdapter(someAdapter1);
    
    mergeAdapter.addAdapter(new ListTitleAdapter(context, "Title2", someAdapter2));
    mergeAdapter.addAdapter(someAdapter2);
    
    mergeAdapter.addAdapter(new ListTitleAdapter(context, "Title3", someAdapter3));
    mergeAdapter.addAdapter(someAdapter3);
    
    mergeAdapter.setNoItemsText("Nothing to display. This list is empty.");
    ((ListView)findViewById(R.id.list)).setAdapter(mergeAdapter);
    

    【讨论】:

    • 关于如何实现项目点击监听器的任何想法?
    • 使用 MultiListener。示例:MultiListener ml = new MultiListener(); ml.registerListener(rentClusterManager); ml.registerListener(saleClusterManager); gmap.setOnCameraChangeListener(ml);
    【解决方案2】:

    添加了这一行:

    setListAdapter(_sla);
    

    线下:

    _sla.addSection("Results", _resultsAdapter);
    

    【讨论】:

      猜你喜欢
      • 2012-11-14
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多