Fast Scroll List View

Posted on 13. Jun, 2010 by in Beginner

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

<ListView
android:id="@+id/myListView"
android:layout_width="fill_parent"
 android:layout_height="fill_parent">
</ListView>

</LinearLayout>
package ch.egsolutions.tutorial;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SectionIndexer;

public class AlphabetIndexer extends Activity {
     ListView myListView;
     ArrayList<String> elements;

     @Override
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);

          // elements
          String s = "QWERTZUIOPASDFGHJKLYXCVBNM";
          Random r = new Random();
          elements = new ArrayList<String>();
          for (int i = 0; i < 300; i++) {

               elements.add(s.substring(r.nextInt(s.length())));

          }
          Collections.sort(elements); // Must be sorted!

          // listview
          myListView = (ListView) findViewById(R.id.myListView);
          myListView.setFastScrollEnabled(true);
          MyIndexerAdapter<String> adapter = new MyIndexerAdapter<String>(
                    getApplicationContext(), android.R.layout.simple_list_item_1,
                    elements);
          myListView.setAdapter(adapter);

     }

     class MyIndexerAdapter<T> extends ArrayAdapter<T> implements SectionIndexer {

          ArrayList<String> myElements;
          HashMap<String, Integer> alphaIndexer;

          String[] sections;

          public MyIndexerAdapter(Context context, int textViewResourceId,
                    List<T> objects) {
               super(context, textViewResourceId, objects);
               myElements = (ArrayList<String>) objects;
               // here is the tricky stuff
               alphaIndexer = new HashMap<String, Integer>();
               // in this hashmap we will store here the positions for
               // the sections

               int size = elements.size();
               for (int i = size - 1; i >= 0; i--) {
                    String element = elements.get(i);
                    alphaIndexer.put(element.substring(0, 1), i);
               //We store the first letter of the word, and its index.
               //The Hashmap will replace the value for identical keys are putted in
               }

               // now we have an hashmap containing for each first-letter
               // sections(key), the index(value) in where this sections begins

               // we have now to build the sections(letters to be displayed)
               // array .it must contains the keys, and must (I do so...) be
               // ordered alphabetically

               Set<String> keys = alphaIndexer.keySet(); // set of letters ...sets
               // cannot be sorted...

               Iterator<String> it = keys.iterator();
               ArrayList<String> keyList = new ArrayList<String>(); // list can be
               // sorted

               while (it.hasNext()) {
                    String key = it.next();
                    keyList.add(key);
               }

               Collections.sort(keyList);

               sections = new String[keyList.size()]; // simple conversion to an
               // array of object
               keyList.toArray(sections);

               // ooOO00K !

          }

          @Override
          public int getPositionForSection(int section) {
               // Log.v("getPositionForSection", ""+section);
               String letter = sections[section];

               return alphaIndexer.get(letter);
          }

          @Override
          public int getSectionForPosition(int position) {

               // you will notice it will be never called (right?)
               Log.v("getSectionForPosition", "called");
               return 0;
          }

          @Override
          public Object[] getSections() {

               return sections; // to string will be called each object, to display
               // the letter
          }

     }
}

Tags: ,

One Response to “Fast Scroll List View”

  1. Tom Hammond

    30. Jan, 2012

    Is it possible to re-use a listview with the Alpha Indexer? For instance, I first display a listView with 1,000 items that are unsorted and set setFastScrollEnabled to true to allow it to be searched quickly, like this:

    myListView = (ListView) findViewById(R.id.myListView);
    myListView.setFastScrollEnabled(true);
    ArrayAdapter arrayAdapter = new ArrayAdapter(getApplicationContext(), android.R.layout.simple_list_item_1,PLAYLIST);
    myListView.setAdapter(arrayAdapter);

    While looking at this list, if the user chooses to sort the list, the listView is “recycled” to a sorted list that uses setFastScroll in addition to the Alpha Indexer to show the letters of the alphabet when scrolling, like this:

    myListView = (ListView) findViewById(R.id.myListView);
    myListView.setFastScrollEnabled(true);
    MyIndexerAdapter adapter = new MyIndexerAdapter(getApplicationContext(), android.R.layout.simple_list_item_1,PLAYLIST_SORTED);
    myListView.setAdapter(adapter);

    Note that the MyIndexerAdapter calls the Alpha Indexer routines for this second use of listView.

    When the program runs, the unsorted list is displayed first. If the user does NOT use the fast scroll on this list, but chooses to display the sorted list, the Alpha Indexer fast scroll on the second (sorted) list works.

    However, if the first unsorted list is shown and the user uses the fast scroll on the unsorted list (without selecting anything), then the users chooses to display the sorted list, the sorted fast scroll does NOT show the Alpha Indexer!

    In other words, manipulating the fast scroller on the unsorted list causes the fast scroller on the second list not to show the Alpha Indexer letter while scrolling the second list. Does anyone know why?

Leave a Reply