Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onItemClick gives index/ position of item on visible page ... not actual index of the item in list ..issue on enabling setTextFilterEnabled

I am creating a list .. the elements of the list are drawn from sqlite database .. I populate the list using ArrayList and ArrayAdapter ...upon clicking the items on the list I want to be able to fire an intent containing info about the item clicked ... info like the index number of the item ..

using the method: onItemClick(AdapterView av, View v, int index, long arg)

I do get index of the item clicked . however it is of the list currently displayed . the problem comes when I do setFilterTextEnabled(true) , and on the app type in some text to to search some item ..and then click it ..rather than giving me the index of the item on the original list it gives me the index on filtered list..

following is the snippet of code:

myListView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int index, long arg) {
            Intent lyricsViewIntent = new Intent(iginga.this, LyricsPage.class);

            lyricsViewIntent.putExtra("title", songList.get((int)arg).getTitle());
            lyricsViewIntent.putExtra("id", songList.get((int)arg).getSongId());
            startActivity(lyricsViewIntent);
        }
    });

    myListView.setTextFilterEnabled(true);

Is there any way I can get the original index /position of the item instead of the one showing in filtered text ...when filtered.

like image 314
Abhinav Avatar asked Mar 26 '10 08:03

Abhinav


4 Answers

I had a bit of a wrestle with this problem recently, and the solution turns out to be fairly simple. You can retrieve the "visible list" by using getListAdapter() on the ListActivity, which reflects the current filtered view of the list.

For example, in your ListActivity subclass's onCreate():

final ListView listView = getListView();
final ListAdapter listAdapter = getListAdapter();

listView .setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        MyClass item = (MyClass) listAdapter .getItem(position);
        // now do something with that item
    }
});

So, ignore the "original" list that you put into the list adapter, and instead ask for the list from the adapter each time the event comes in.

like image 118
skaffman Avatar answered Oct 19 '22 17:10

skaffman


Abhinav I completely understand your problem as I have been struggling with the same issue for the past two days. I didn't realize the values of "int position" and "int id" change as you use the soft keyboard to filter data until I started using breakpoints on the debugger. Hope this code can give you a better idea of how to fix your issues. I ended up writing a for loop so that I could match the toString() of the filtered list with the toString() of the unfiltered list. This way I could retrieve/correct the "int position" value.

public class FacultyActivity extends ListActivity
{   
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        // Retrieves the array stored in strings.xml
        final String[] facultyList1 = getResources().getStringArray(R.array.professor_name);
        final String[] facultyList2 = getResources().getStringArray(R.array.professor_email);

        // Develop an array based on the list_view.xml template
        setListAdapter(new ArrayAdapter<String>(this, R.layout.faculty, facultyList1));
        final ListView lv = getListView();

        // Allow the user to filter the array based on text input
        lv.setTextFilterEnabled(true);

        // Handle the user event where the user clicks on a professor's name
        lv.setOnItemClickListener(new OnItemClickListener() 
        {
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
          {

              /* Filtering text changes the size of the array[index].  By clicking on a filtered 
               * entry the int position and long id does not correlate to the original array list.
               * This block of code will search the original array based on the toString() function
               * and for loop the orignial array to find the matching string, retrieving the 
               * correct index/position.
               */
              String name = lv.getItemAtPosition(position).toString();

              for (int index = 0; index < facultyList1.length; index++)
              {
                  if (name.equals(facultyList1[index]))
                  {
                      position = index;
                      break;
                  }
              }

              Bundle bundle = new Bundle();
              bundle.putString("email", facultyList2[position]);
              startActivity(new Intent(FacultyActivity.this, EmailActivity.class).putExtras(bundle)); 
          }
        });  
    }
}
like image 29
Arthur Avatar answered Oct 19 '22 16:10

Arthur


One of the ways of doing this could be Tagging the view with its index when drawing them View#setTag() and reading them when ever you want with View#getTag()

like image 1
Samuh Avatar answered Oct 19 '22 16:10

Samuh


I think that this is a bug that should be fixed: if you click (with the mouse) on entry number 150 for instance, you get back the name of entry 150 and an id of 150. But if you type in characters that give you entry 150 back and it's the first of three with the same characters you've typed in, you get back 0 and the name of entry 0 (which of course in your original list is not what you want). This should return the id and name for entry 150 if filtered and to have to do what abhinav did above (albeit, useful and worked for me), is kludgy in my not so humble opinion.

like image 1
user941601 Avatar answered Oct 19 '22 15:10

user941601