android 将多个适配器附加到一个适配器

发布于 2024-12-13 10:18:11 字数 1288 浏览 2 评论 0原文

我一直在使用 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)

I have been using the SeparatedListAdapter which is very well known and works perfectly, but it seems that I cannot use the addSection() to add a SimpleAdapter, because the application is terminated. I'm providing some code to show you what I'm trying to do and get some guidance in order solve this issue. Please let me know if you need any other piece of code or anything:

// 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜清冷一曲。 2024-12-20 10:18:12

您可以将 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);

You can use MergeAdapter for your ListView. This is my modified and fully tested version.

/**
* 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();
        }
    }
}

You also will need ListTitleAdapter to put some titles before each adapter if you want.

  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;
  }
  }

And here is small example on how to use these two classes.

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);
不顾 2024-12-20 10:18:12

添加了这一行:

setListAdapter(_sla);

在该行下方:

_sla.addSection("Results", _resultsAdapter);

Added this line:

setListAdapter(_sla);

below the line:

_sla.addSection("Results", _resultsAdapter);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文