5

I'm using Sharkey's SeparatedListAdapter class in order to have a ListView that is separated by sections.

The class works great, but the problem I'm having is in my onListItemClick() handler. If I have the following sectioned list:

---------
| A     |
---------
| Alex  |
| Allan |
---------
| B     |
---------
| Barry |
| Bart  |
| Billy |
| Brian |
---------
| C     |
---------
etc...

When you want to click on an item in the list, you get the position of the item and then do something with it.

In my case, my list is a dynamic list of people's names. The names come from a database that is put into a List<CustomClass> before going into list. It's important for me to know the position of the item that I click on because I use the item position to determine other information about the person in the List object.

Now, the problem is this: When you click an item in the list, the headers count as items, even though they are unclickable. In the above example, the positions in the list are as follows

Alex = 1
Allan = 2
Barry = 4
Bart = 5
Billy = 6
Brian = 7

But in my original List object the order is like so

Alex = 0
Allan = 1
Barry = 2
Bart = 3
Billy = 4
Brian = 5

So whenever I click on an item, like Alex, my code runs the onClick handler, determines that Alex is at position 1 in the and then retrieves Allans info from the List instead of Alex's.

Do you see the delima here? What is the approach I should take to this problem?

Jake Wilson
  • 88,616
  • 93
  • 252
  • 370

4 Answers4

7

You could use setTag() for your every item in the listView. This can be done by adding this tag before you return the view from getView() function in the listAdapter. lets say your list adapter return convertView ,then in the list adapter.

    public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null)
            {
                convertView = mLayoutInflater.inflate(R.layout.morestores_list_item, null);
                holder = new ViewHolder();

                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            // populate holder here, that is what you get in onItemClick.
                    holder.mNameofItem = "NameofaPerson";
            return convertView;
        }

static class ViewHolder {
        TextView mName;
        Button mAction;
        ImageView mLogo;
            // use this class to store the data you need, and use appropriate data types.
            String mNameofItem.
    }

when ever you get a click on the list item, use

public void onItemClick(AdapterView<?> arg0, View convertView, int arg2,
            long arg3) {
                ViewHolder holder = (ViewHolder) convertView.getTag();
                // holder has what ever information you have passed.
                String nameofItemClicked = holder.mNameofItem;
                // access the information like this.
    }

This approach doesn't need the position of the item in the list, just wanted to let you know different approach.

HTH.

Yashwanth Kumar
  • 28,931
  • 15
  • 65
  • 69
1

For anyone else I too recently ran into this problem and ended up here, I solved by:

First altering the Map to take an 'id'

public Map<String,?> createItem(String title, String caption, String id) { 
  Map<String,String> item = new HashMap<String,String>(); 
  item.put(ITEM_TITLE, title); 
  item.put(ITEM_CAPTION, caption); 
  item.put("id", id); // Add a unique id to retrieve later
  return item;}

Second when adding a section make sure to include an id:

 List<Map<String,?>> GeneralSection = new LinkedList<Map<String,?>>(); 
          GeneralSection.add(createItem(FirstName[GeneralInt] + " " + LastName[GeneralInt], Whatever[GeneralInt], UniqueId[GeneralInt]));   
//Unique id could be populated anyway you like, database index 1,2,3,4.. for example like above question.
          adapter.addSection("GeneralSection ", new SimpleAdapter(getActivity(), GeneralSection , R.layout.list_complex, 
            new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));

Finally Use a Map in ItemClickListener to retrieve 'id' of the correct position:

  @Override
        public void onItemClick(AdapterView<?> arg0,  View v, int position, long arg3) {
            // TODO Auto-generated method stub

            Map<String, String> map = (Map<String, String>) arg0.getItemAtPosition(position);
            String UniqueId = map.get("id");
            Log.i("Your Unique Id is", UniqueId); 
//Can then use Uniqueid for whatever purpose
//or any other mapped data for that matter..eg..String FirstName = map.get("ITEM_TITLE");


    }

Hope this helps someone.

1

My solution was instead of getting the position in the list and then using that to get the object from the ListArray or Hash, to just get the object in that position in the adapter and then retrieving whatever custom parameter or method from it that I needed. It's kind of obvious now but wasn't making sense at first.

UPDATE It's a long bit of code so I will just give an overview:

Instead of passing in a String for the list item, pass in a custom object. Lets say this object has two different values it stores. A name (retrievable by public method getName()) and an ID (retrievable by getId()).

You have to override the getView() method for the adapter class and make it use the getName() method of the object and use that text to display in the list item.

Then, when the item is clicked, just get the object from the adapter at that position and then get the ID:

int id = adapter.get(position).getId();
// Then do something with the ID, pass it to an activity/intent or whatever.

Also I ditched the SeparatedListViewAdapter in favor of this. Much better and more flexible imo.

Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
  • can you give me code for this "just get the object in that position in the adapter" thanks – Jovan Oct 12 '11 at 22:46
  • I too ditched the SeparatedListViewAdapter in favor of the link you provided. Much simpler. :). Thanks for that link. – Veer Oct 03 '12 at 10:12
1
 int idNo= adapter.get(position).getId();

you can try this code...

Girish Patel
  • 1,270
  • 4
  • 16
  • 30