when givingListviewafter adding a Headerview (code below), we found thatOnitemclickin the method.
position
The value of the parameter is not what we expected, such as clicking on the first row of the ListView, we expect
position
is 0, but actually it is 1, which means it is counted from the header instead of the first line.
123456789101112131415161718 |
@Override
protected
void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.home);
mAdapter =
new
MyAdapter(
this
);
mListView = (ListView) findViewById(R.id.list);
mListView.addHeaderView(getLayoutInflater().inflate(R.layout.list_header));
mListView.setAdapter(mAdapter);
mListView.setOnClickListener(
this
);
}
@Override
public
void
onItemClick(AdapterView<?> parent, View v,
int position,
long
id) {
doSomething(mAdapter.getItem(position));
}
|
Google, found a foreigner issue a bug, and I encountered the same problem, but this bug was Romainguy reject off, the reason is that you use the wrong, please use Getadapter. This answer is too concise, completely unable to understand, so had to study the ListView code, finally understand his meaning. Put the Addheaderview and the Setadapter method down.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
/**
* Add a fixed view to appear at the top of the list. If addHeaderView is
* called more than once, the views will appear in the order they were
* added. Views added using this call can take focus if they want.
* <p>
* NOTE: Call this before calling setAdapter. This is so ListView can wrap
* the supplied cursor with one that that will also account for header
* views.
*
* @param v The view to add.
* @param data Data to associate with this view
* @param isSelectable whether the item is selectable
*/
public
void
addHeaderView(View v, Object data,
boolean
isSelectable) {
if
(mAdapter !=
null
) {
throw
new
IllegalStateException(
"Cannot add header view to list -- setAdapter has already been called."
);
}
FixedViewInfo info =
new
FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
} /**
* Sets the data behind this ListView.
*
* The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
* depending on the ListView features currently in use. For instance, adding
* headers and/or footers will cause the adapter to be wrapped.
*
* @param adapter The ListAdapter which is responsible for maintaining the
* data backing this list and for producing a view to represent an
* item in that data set.
*
* @see #getAdapter()
*/
@Override
public void
setAdapter(ListAdapter adapter) {
if
(
null
!= mAdapter) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if
(mHeaderViewInfos.size() >
0
|| mFooterViewInfos.size() >
0
) {
mAdapter =
new
HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
}
else
{
mAdapter = adapter;
}
//其它的一些代码这里省略之...
}
|
It is clear from both the code and the comments that it addHeaderView
must be setAdapter
called before, and if not, addHeaderView
throws an exception. Why is Android doing this? This is because, at setAdapter
the time, I do some special handling of this situation (that is, when I add the header incorrectly position
). setAdapter
internally determine whether the current ListView has a header or footer, if not, directly using the parameters to pass in the adapter; If so, replace the parameters with a decorated HeaderViewListAdapter
. The HeaderViewListAdapter
mission of this is to exclude headers and footer, and let position
the parameters of methods (including GetItem, Getitemid, of course) position
return correctly.
Analysis here, the solution is out: onItemClick
do not directly use our declared adapter, but with the decorated in the ListView adapter. The method that gets it is called parent.getAdapter()
. Of course, if the ListView does not have headers and footer, it is not a problem to use the declared adapter directly, but it is better to use decorated adapter in order to avoid errors.
Change the Onitemclick to the following.
1234 |
@Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { doSomething(parent.getAdapter().getItem(position)); } |
This article by Roy was originally posted in: http://blog.chengbo.net/2012/03/09/ Onitemclick-return-wrong-position-when-listview-has-headerview.html, you can reprint, distribute and print in the event that you keep the article intact and retain this statement.
When the ListView has a header, the position in the Onitemclick is incorrect.