Does the "position" parameter in the onItemClick reference the position in the Adapter, which might include, say, the footer and header as well. I'm asking because I want to be able to pass the actual position in the underlying array that I'm using with my adapter. Can I just pass "position" and I'll be good to go?
If I remember correctly the position is the position in your items array. Header and footer items I do not think get included, because your overridden method getPosition() simple returns the position you are seeking within the array of items.
In answer to your question, yes, headers and footers are included in the position parameter.
The documentation for onItemClick states the parameters are as follows:
parent The AdapterView where the click happened.
view The view within the AdapterView that was clicked (this will be a view provided by the adapter)
position The position of the view in the adapter.
id The row id of the item that was clicked.
So if you're looking to fetch an object from your underlying array, you should use the long id parameter instead, which returns the underlying array index:
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// Get the item that was clicked
Object objectToUse = myAdapter.getItem( (int) id );
}
Related
I have a listview itemClickListener that should get the model instance associated with the row clicked.
I read about tags in http://developer.android.com/reference/android/view/View.html#setTag(int, java.lang.Object)
I know that listview recycles rows, so it would not be a good idea to use v.setTag(currentItem), because that would result in an earlier row being associated with a later item.
So to solve my original problem, it looks like I need to use setTag(int, object) where the body of my click handler needs to know the unique key. The documentation states to use a resource id value, but that is not unique amongst multiple rows. How do I get the model instance for the row I clicked on?
You should just be able to grab the item out of your adapter like this:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
ListAdapter a = (ListAdapter)parent.getAdapter();
Object itemAtPosition = a.getItem(position);
}
getItemIdAtPosition() is a function in android used to get the id of an item in a list view given its position
is there any way of doing the reverse, i.e. getting the position of an item is a list view given its id?
No. You have to do it manually. Create a public method inside the adapter you are using; in that method, loop on the adapter items and check each item id. If it is == to the method param, then return the index.
public int getItemPosition(long id)
{
for (int position=0; position<mList.size(); position++)
if (mList.get(position).getId() == id)
return position;
return 0;
}
Update: You might as well save a HashMap for position/id in your adapter, if lookup performance represents a problem for your use case.
Update: If you want to use this method outside the adapter, then use below:
private int getAdapterItemPosition(long id)
{
for (int position=0; position<mListAdapter.getCount(); position++)
if (mListAdapter.get(position).getId() == id)
return position;
return 0;
}
Not sure if the question is still open. Nevertheless, thought I will share how I did it so that it may help someone who is looking to do the same thing.
You can use the tag feature of a view to store the mapping between that view's id and its position in the list.
The documentation for tags on the android developer site explains it well:
http://developer.android.com/reference/android/view/View.html#Tags
http://developer.android.com/reference/android/view/View.html#setTag(int, java.lang.Object)
http://developer.android.com/reference/android/view/View.html#getTag(int)
Example:
In the getView method of your list adapter, you can set the mapping for that view's id and its position in the list, something like:
public View getView (int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
// create your view by inflating a xml layout resource or instantiating a
// custom view class
}
else
{
// Do whatever you want with the convertView object like
// finding a child view that you want to set some property of,etc.
}
// Here you set the position of the view in the list as its tag
convertView.setTag(convertView.getId(),position);
return convertView;
}
To retrieve the position of the view, you would do something like:
int getItemPosition(View view)
{
return view.getTag(view.getId());
}
A point to be noted is that you do need to have a reference to the View whose position you want to retrieve. How you get hold of the View's reference is dependent on your specific case.
No. Depending on what adapter you're using to back your ListView the id and position may be the same (I haven't looked at all BaseAdapter subclasses so I cannot say for sure). If you look at the source code for ArrayAdapter you will see that getItemId actually returns the position of the object in the adapter. If the position and id are the same, there is no need to use one to get the other. Otherwise you just need to search the adapter for the object your looking for - using either position or id - and you can find the other value.
If what you're talking about is getting objects using some unique key - i.e. one that you define - that can be done. What you need to do is set up your adapter to take a HashMap instead of an ArrayList or regular List of objects. Then you can create your own method to find by key by simply pulling that value from the HashMap.
it's too late to answer but for benefit...
for example if you have listview and you want to get id with click listener you can get it by >>
cListview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// for id or any informations
itemID = String.valueOf(catList.get(position).getItemID());
// for name or any informations
itemName = String.valueOf(catList.get(position).getItemName());
I've read lots of tutorials from my manual and on the internet that explain the getView method, but I haven't understood why they use it.
Could anyone explain it to me with some examples or snippets?
getItem() returns the item's data object. It provides a way for you to access data in the adapter. For example, your array adapter holds string elements, getItem() returns a string object.
getView() is used to construct or reuse the child item of your AdapterView.
AdapterView is a view that contains multiple items. For example, a ListView contains some items that have the same (or might not) structure. getView() is used to build the View at some position and fill it with data.
getItem() is used to get the item that provides a data for the specified View item.
For example, getItem() must return a String or CharSequence if you have a ListView of text items. This is made for convenience, for example in your onItemClickListener
#Override
public void onItemClick(AdapterView<?> av, View view, int pos,
long arg3) {
String selectedText = (String) av.getItemAtPosition(pos);
// or av.getAdapter().getItem(pos);
}
I have a custom ListView with two TextViews both containing different values. What I want to be able to do it get the contents from one of these TextViews when an item is clicked.
This is the code I have so far:
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String value;
// value = (get value of TextView here)
}
});
I want to be able to assign value to the text of one of the TextView's.
Although #Sam's suggestions will work fine in most scenarios, I actually prefer using the supplied AdapterView in onItemClick(...) for this:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Person person = (Person) parent.getItemAtPosition(position);
// ...
}
I consider this to be a slightly more fool-proof approach, as the AdapterView will take into account any header views that may potentially be added using ListView.addHeaderView(...).
For example, if your ListView contains one header, tapping on the first item supplied by the adapter will result in the position variable having a value of 1 (rather than 0, which is the default case for no headers), since the header occupies position 0. Hence, it's very easy to mistakenly retrieve the wrong data for a position and introduce an ArrayIndexOutOfBoundsException for the last list item. By retrieving the item from the AdapterView, the position is automatically correctly offset. You can of course manually correct it too, but why not use the tools provided? :)
Just FYI and FWIW.
You have a few options. I reference the code from your previous question.
You can access this data from the row's layout view:
ViewHolder holder = (ViewHolder) view.getTag();
// Now use holder.name.getText().toString() and holder.description as you please
You can access the Adapter with position:
Person person = mAdapter.getItem(position);
// Now use person.name and person.description as you please
(By the way in your Person class, name and description are public so you don't need the get methods.)
Override following method in adaterclass.
public String[] getText() {
return text;
}
In the following example, how would I access the "position" variable from outside the parent class?
void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Country country = (Country) parent.getAdapter().getItem(position);
spinner2.setAdapter(new ArrayAdapter(country.getStates());
}
You could pass the position value outside, but you also have to know something about the adapter and the data source of the adapter. If your adapter is using an array for the data source, position is usually the position of the item in the array. So if you have some other access point to the array, the position would be that element. If the data source of the adapter is a Cursor, position won't help you much outside because you can't be sure of which record the Cursor was pointing to at that position. So unfortunately, the answer is "it depends". Using id is better if the data source is a content provider since you can append the id to the base Uri and access the record that way outside of this callback.