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

时间:2010-09-16 20:04:23

标签: android listview header

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

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

class IconicAdapter extends ArrayAdapter<String> {
    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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:gravity="right"
>    

  <TextView
    android:id="@+id/label"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:paddingRight="10dp"
    android:paddingLeft="10px"
    android:gravity="left"
    android:textStyle="bold"
    />    
</LinearLayout>

row_iconic.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:gravity="right"
>    

  <TextView
    android:id="@+id/label"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="16sp"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:paddingRight="10dp"
    android:paddingLeft="44px"
    />  
    <ImageView
    android:id="@+id/rowicon"
    android:layout_width="40dp"
    android:paddingRight="10dp"
    android:paddingTop="10dp"
    android:layout_height="30dp"        
    android:src="@drawable/icon"
    />    
</LinearLayout>

4 个答案:

答案 0 :(得分:13)

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

看看Mark Murphy的SectionedListAdapter,GPL,它采用第一种方法(基于Jeff Sharkey的代码)或他的MergeAdapter,并查看this SO question

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

答案 1 :(得分:7)

如果您想要返回不同的布局(例如商品和标题),则必须使用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。 ; - )

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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