androidandroid-listviewandroid-arrayadaptersectionindexer

section indexer get section for position returns 0


In my project I have class that extends ArrayAdapter<String> and implements SectionIndexer. When implementing methods getPositionForSection and getSectionForPosition I have found some strange behaviour.

Why section indexer works properly when getSectionForPosition returns 0?

public int getSectionForPosition(int position) {
    return 0;
}

this implementation is used in many tutorials, for example:

http://androidopentutorials.com/android-listview-fastscroll/

http://www.survivingwithandroid.com/2012/12/android-listview-sectionindexer-fastscroll.html

Documentation says that

Given a position within the adapter, returns the index of the corresponding section within the array of section objects.

so if my list have 5 items starting with letter "A" and some items starting with letter "B", then getSectionForPosition(5) should return 1.


Solution

  • While the basic functionality of the sectionIndexer (scrolling through the section indices when pulling the scrollbar thumb) is unaffected, returning a constant in the method getSectionForPosition can lead to a misbehaviour of the scrollbar positioning when swiping through the list (e.g. the scrollbar moving out of the window on the y-axis).

    Apparently this misbehaviour only occurs when the list or single sections exceed a certain length, so for shorter lists the indexer might seem to work correctly (but in fact doesn't). I experienced this misbehaviour in larger lists when returning a constant in the above method several times and fixed it by implementing getSectionForPosition in a correct way.


    However, since it might be interesting for others I can provide a sample implementation of that method. Let azIndexer be a HashMap containing a correct section -> position mapping of my indices and listItems be the items arranged by the adapter. The following builds a position -> sectionIndex mapping stored in positionIndexer.

    List<Integer> values = new ArrayList();
    for (int i : azIndexer.values()) {
        values.add(i);
    }
    values.add(listItems.size()-1);
    Collections.sort(values);
    
    int k = 0;
    int z = 0;
    for(int i = 0; i < values.size()-1; i++) {
        int temp = values.get(i+1);
        do {
            positionIndexer.put(k, z);
            k++;
        } while(k < temp);
        z++;
    }
    

    which will then be used in the getSectionForPosition method:

    @Override
    public int getSectionForPosition(int position) {
        return positionIndexer.get(position);
    }