section indexer get section for position returns 0

2019-01-20 06:30发布

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.

2条回答
Luminary・发光体
2楼-- · 2019-01-20 06:35

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);
}
查看更多
We Are One
3楼-- · 2019-01-20 06:40

Your callback method getPositionForSection(int section) needs to be implemented to give the right position which is used by setSelection to return the right position where you want to scroll on touch of SectionIndexer on rightside.

Make sure you are doing this

this.setSelection(((SectionIndexer) getAdapter()) .getPositionForSection(currentPosition));

You need to implement two callback methods

@Override
public Object[] getSections() { 
  Log.d("ListView", "Get sections"); 
  String[] sectionsArr = new String[sections.length()]; 
  for (int i=0; i < sections.length(); i++) 
  sectionsArr[i] = "" + sections.charAt(i);

   return sectionsArr; 
 }

This final callback and you are done here

@Override 
public int getPositionForSection(int section){ 
  Log.d("ListView", "Get position for section"); 
  for (int i=0; i < this.getCount(); i++) { 
  String item = this.getItem(i).toLowerCase(); 
  if (item.charAt(0) == sections.charAt(section)) 

 return i; 
} 

return 0; 
}
查看更多
登录 后发表回答