如何使用addHeaderView()在单个ListView中添加多个标头?

Android的addHeaderView()可用于在单个ListView中添加多个标头吗? 有人可以举例说明如何做到这一点吗?

我能够通过操纵IconicAdapter类来完成我想要的…有什么理由不这样做吗? 我觉得这可以修改为更高级的实现。 在我的情况下,我知道我将有两个部分,每个部分有一个标题+ 2行。

class IconicAdapter extends ArrayAdapter { IconicAdapter() { super(ContactTabProfileResource.this, R.layout.row_iconic, mArrayList); } public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = getLayoutInflater(); View row = null; if(position == 1 || position == 5) { // phone row = inflater.inflate(R.layout.row_iconic, parent, false); TextView label =(TextView)row.findViewById(R.id.label); label.setText(mArrayList.get(position)); ImageView icon = (ImageView)row.findViewById(R.id.rowicon); icon.setImageResource(R.drawable.icon_phone); } else if (position == 2 || position == 6) { // email row = inflater.inflate(R.layout.row_iconic, parent, false); TextView label =(TextView)row.findViewById(R.id.label); label.setText(mArrayList.get(position)); ImageView icon = (ImageView)row.findViewById(R.id.rowicon); icon.setImageResource(R.drawable.icon_email); } else if (position == 0 || position == 4) { // section header row = inflater.inflate(R.layout.row_header, parent, false); TextView label =(TextView)row.findViewById(R.id.label); label.setText(mArrayList.get(position)); label.setBackgroundColor(Color.GRAY); } else if (position == 3) { // section divider row = inflater.inflate(R.layout.row_header, parent, false); TextView label =(TextView)row.findViewById(R.id.label); label.setText(" "); } return(row); } } 

然后我创建了两个不同的XML布局。 row_header.xml用于标题行,row_iconic.xml用于非标题行,其中包含图标。

row_header.xml

     

row_iconic.xml

      

你想要什么Android开发人员可能会调用列表分隔符或子标题(“标题”和“页脚”只存在于列表的顶部或底部)。 如何做到这一点的要点是使用一个包装其他ListAdapter的ListAdapter,并且足够聪明,可以返回某些行的标题视图types并跟踪偏移量,或者将这些分隔符视图包装在它们自己的迷你适配器中。

看一下Mark Murphy的SectionedListAdapter ,GPL,它采用第一种方法(基于Jeff Sharkey的代码)或他的MergeAdapter ,并看到这个SO问题 。

它与iPhone上智能列表子标题的优雅处理相去甚远,但是使用MergeAdapter非常简单,并且一旦你完全适应了适配器内部的情况,就会非常灵活。

如果要返回不同的布局(例如,项目和标题),则必须使用getItemViewType(int position) 。 所以你的适配器代码应如下所示:

 private static final int TYPE_HEADER = 0; private static final int TYPE_ICONIC = 1; @Override public int getViewTypeCount() { return 2; // we have two types, so just return 2 } @Override public int getItemViewType(int position) { // TODO: return TYPE_HEADER here if this position is a header, otherwise return TYPE_ICONIC } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO: return the appropriate layout // hint: you might call getItemViewType(position) yourself here to know of which type the layout is } 

这基本上就是它的工作原理。 要确保标头不可选,您可能希望抛弃ArrayAdapter并改为使用ListAdapter,重写isEnabled(int position)以返回标头视图的false。 😉

您可以多次调用addHeaderView()来添加任意数量的标头。 在将适配器设置为列表视图之前,必须执行此操作。

您也可以使用此类作为示例。 它支持“部分”和“动作”,其中“部分”只是“动作”(项目)的组,它们具有不可点击和不可选择的项目标题。 “Actions”可以指定onClick处理程序,当按下此“action”时将调用该处理程序(如果存在)。 它还包含ImageLoader ,用于从Web获取“操作”的图像。