Even if we have enabled fast scroll, it is still difficult to know where we are in the list. To get around this, we make use of section indexes.
Making a list show a section index popup while scrolling is quite easy, requiring only that the adapter implements the ISectionIndexer
interface. Let's take a look at the following steps:
listView.FastScrollEnabled = true;
ISectionIndexer
interface:public class PeopleAdapter :
BaseAdapter<Person>, ISectionIndexer {
public int GetPositionForSection(int section) {
}
public int GetSectionForPosition(int position) {
}
public Java.Lang.Object[] GetSections() {
}
}
private readonly Context context; private readonly List<Person> data; private readonly Dictionary<string, List<Person>> sectionData; private readonly List<string> sections; public PeopleAdapter(Context context, List<Person> data) { this.data = data; this.context = context; sectionData = data .GroupBy(p => p.Name.Substring(0, 1).ToUpper() .ToDictionary(g => g.Key, g => g.ToList()); sections = sectionData.Select(s => s.Key).ToList(); }
GetSections()
method, which returns all the sections in the data:public Java.Lang.Object[] GetSections() { return sections .Select(s => (Java.Lang.Object)s) .ToArray(); }
public int GetSectionForPosition(int position) { Person person = data[position]; string key = sectionData .First(g => g.Value.Contains(person)) .Key; return sections.IndexOf(key); }
public int GetPositionForSection(int section) { string key = sections[section]; Person person = sectionData[key].First(); return data.IndexOf(person); }
Even if we have enabled fast scroll, it is still difficult to know where we are in the list as the items are moving very quickly. We might not be able to see which items they are, so we have to stop scrolling and check. We can add to the improvement of fast scroll by using a section index.
A section index is a simple popup that appears as we fast-scroll, displaying a value that we choose representing the section of the list that the visible items are in. The section index value can be anything as it is simply a grouping mechanism that we determine. For example, it can be the first letter of the items.
After enabling fast scroll, the only additional thing we need to do is ensure that our adapter implements the ISectionIndexer
interface. There are three methods to implement—two provide a means for the list to find particular positions and one provides the indexes.
The GetSection()
method returns a simple array of all the indexes; this is only requested once and can be precalculated to improve performance. In this method, we return an array of the extracted indexes from the data. The order of the items is important as we will refer to a particular item by position.
The GetSectionForPosition()
method returns the position of a section that contains the particular data item. This position refers to a position in the array returned by the GetSection()
method. In order to get this position, we are provided with the position of the data item, which we can use to work backwards to obtain the section.
The GetPositionForSection()
method returns the position of the first item in a particular section. This position refers to a position in the original data collection. We are provided with the position of a section and work forward to obtain the first item in that section.
As the sections will only change if the data is changing, we can precalculate the entire set of sections and indexes, and then just return the values from the respective methods.
Depending on the type of adapter we use, adding items to it may automatically let the list view know that it needs to refresh the sections. If we are using a custom adapter, we will have to manually do this by invoking the NotifyDataSetChanged()
method on the adapter. This will trigger the list view to obtain a new set of sections.
As the GetSections()
method is only called once every time the data changes, we can place the logic that precalculates the sections and indexes here, reducing the load on the other methods to a simple lookup.