Using section indexes

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.

How to do it...

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:

  1. In order to enable the section index, we need to ensure that fast scroll is enabled on the list view:
    listView.FastScrollEnabled = true;
  2. Then we ensure that the list adapter implements the ISectionIndexer interface:
    public class PeopleAdapter :
      BaseAdapter<Person>, ISectionIndexer {
      public int GetPositionForSection(int section) {
      }
      public int GetSectionForPosition(int position) {
      }
      public Java.Lang.Object[] GetSections() {
      }
    }
  3. We can calculate all of these values on-the fly but, for performance reasons, we do some of it in the constructor. Here, we group the data by the first letter of the name:
    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();
    }
  4. Once we have the main groups, we can start by implementing the GetSections() method, which returns all the sections in the data:
    public Java.Lang.Object[] GetSections() {
      return sections
        .Select(s => (Java.Lang.Object)s)
        .ToArray();
    }
  5. Next, we implement the method that returns the position of a section that contains a particular data item:
    public int GetSectionForPosition(int position) {
      Person person = data[position];
      string key = sectionData
        .First(g => g.Value.Contains(person))
        .Key;
      return sections.IndexOf(key);
    }
  6. Lastly, we implement the method that returns the position of the first item in a particular section:
    public int GetPositionForSection(int section) {
      string key = sections[section];
      Person person = sectionData[key].First();
      return data.IndexOf(person);
    }

How it works...

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.

Note

The section index is a simple popup that appears in order to let the user know the section of the list that they are in.

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.

There's more...

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.

See also

  • The Using a BaseAdapter with arbitrary data recipe
  • The Optimizing the ListView recipe
  • The Enabling fast scrolling recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset