Android 如何使用 addHeaderView() 在单个 ListView 中添加多个标题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3730358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add multiple headers throughout a single ListView with addHeaderView()?
提问by Chris
Can Android's addHeaderView() be used to add multiple headers throughout a single ListView? Can someone give an example of how to do this?
可以使用 Android 的 addHeaderView() 在单个 ListView 中添加多个标头吗?有人可以举例说明如何做到这一点吗?
I was able to accomplish what I wanted by manipulating the IconicAdapter Class... is there any reason why I should not do it this way? I feel this could be modified for more advanced implementations. In my case, I know that I will have two sections, with a header + 2 rows in each section.
我能够通过操作 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);
}
}
Then I created two different XML layouts. row_header.xml is for the header rows and row_iconic.xml is for the non-header rows, which contain an icon.
然后我创建了两个不同的 XML 布局。row_header.xml 用于标题行,row_iconic.xml 用于包含图标的非标题行。
row_header.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
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>
采纳答案by Yoni Samlan
What you want Android developers might call a list separator or subheading ("headers" and "footers" live only at the top or bottom of the list). The gist of how you can do this is by using a ListAdapter that wraps other ListAdapters and is smart enough to return a header view type for certain rows and keep track of the offsets, or wraps those separator views in their own mini adapters.
您想要的 Android 开发人员可能会调用列表分隔符或副标题(“页眉”和“页脚”仅位于列表的顶部或底部)。如何做到这一点的要点是使用包装其他 ListAdapter 的 ListAdapter 并且足够聪明,可以返回某些行的标题视图类型并跟踪偏移量,或者将这些分隔符视图包装在它们自己的迷你适配器中。
Take a look at Mark Murphy's SectionedListAdapter, GPL, which takes the first approach (based on code by Jeff Sharkey), or his MergeAdapter, and see this SO question.
看看 Mark Murphy 的SectionedListAdapter,GPL,它采用第一种方法(基于 Jeff Sharkey 的代码),或者他的MergeAdapter,并看到这个 SO question。
It's a far cry from the graceful handling of smart list subheadings on the iPhone, but it is fairly straightforward to use MergeAdapter and very flexible once you wrap your head around exactly what's going on inside the adapters.
这与 iPhone 上智能列表副标题的优雅处理相去甚远,但使用 MergeAdapter 相当简单,而且一旦您完全了解适配器内部发生的事情,就非常灵活。
回答by mreichelt
If you want to return different layouts (e.g. items & headers) you have to use getItemViewType(int position)
. So your adapter code should look like this:
如果您想返回不同的布局(例如项目和标题),您必须使用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
}
That's basically how it works. To ensure the headers are not selectable, you might want to throw ArrayAdapter away and use ListAdapter instead, overriding isEnabled(int position)
to return false for your header views. ;-)
这基本上就是它的工作原理。为确保标题不可选择,您可能希望丢弃 ArrayAdapter 并改用 ListAdapter,覆盖isEnabled(int position)
为您的标题视图返回 false。;-)
回答by Nathan Schwermann
You can add as many headers as you like by calling addHeaderView() multiple times. You have to do it before setting the adapter to the list view.
您可以通过多次调用 addHeaderView() 添加任意数量的标题。您必须在将适配器设置为列表视图之前执行此操作。
回答by shaman.sir
You can also use this classas an example. It supports "sections" and "actions", where "sections" are just groups of "actions" (items), they have non-clickable and non-selectable item - header. "Actions" can specify onClick
handler which will be called when this "action" will be pressed, if exist. It also contains ImageLoader
to fetch images for the "actions" from the web.
您也可以使用此类作为示例。它支持“部分”和“动作”,其中“部分”只是“动作”(项目)的组,它们具有不可点击和不可选择的项目 - 标题。“动作”可以指定onClick
当这个“动作”被按下时将被调用的处理程序(如果存在)。它还包含ImageLoader
从网络获取“动作”的图像。