一 遇到问题
ListView HeaderView使用过程中遇到的问题
1. 必须在setAdapter之前执行addHeaderView方法,否则会出现以下异常
java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
二 分析源码查找原因
先来看问题1,查看下ListView.addHeaderView()源码分析原因
public void addHeaderView(View v, Object data, boolean isSelectable) {
// 只要mAdapter不为空就抛出此异常
if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) {
throw new IllegalStateException(
"Cannot add header view to list -- setAdapter has already been called.");
}
......
}
再分析下问题2,查看ListView.setAdapter()源码分析原因
public void setAdapter(ListAdapter adapter) {
.....
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
.....
}
原来使用了新的adapter
三 为什么HeaderView需要包装一个HeaderViewListAdapter?
为什么addHeaderView时adapter必须为空
1. 先来看下ListView的继承体系
ListView -> AbsListView -> AdapterView -> ViewGroup
2. ListView继承自ViewGroup,如果需要添加视图只能通过ViewGroup.addView()添加,而在AdapterView.addView中可以看到此方法已经不让使用
public void addView(View child) {
throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
}
3. 只能通过adapter的getview处理添加view,ListView内部是如何添加View?以下是方法调用堆栈
AbsListView.onTouchEvent ->
AbsListView.scrollIfNeeded ->
AbsListView.trackMotionScroll ->
AbsListView.fillGap ->
ListView.fillDown/fillUp/fillFromMiddle ->
ListView.makeAndAddView ->
ListView.setupChild ->
ListView.addViewInLayout
也可以在第一个item的布局中添加,但是这种方式会对ListView造成影响
2013-04-22 删除position引出的问题,拆分出一个独立的文章之前放到一起有点乱