Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create easy alphabetical scrolling in ListView?

I'm looking to emulate the functionality in the latest Music app, namely the nice little cursor that pops up which allows one to scroll super fast to the artist/album/track they're looking for:

"Super Scrolling"Regular Scrolling

Is there a method to enable functionality like this in a ListView in the Android SDK?

like image 821
Naftuli Kay Avatar asked Feb 25 '11 21:02

Naftuli Kay


5 Answers

Have your list adapter implement SectionIndexer. The music app also makes use of AlphabetIndexer to do some of the heavy lifting. Also use setFastScrollEnabled(true) on the actual ListView to enable this.

Edit: If you're not using a CursorAdapter, you won't be able to use AlphabetIndexer. You might try looking at the implementation here and seeing how hard it would be to adapt it to work with an ArrayAdapter.

like image 182
Erich Douglass Avatar answered Nov 14 '22 23:11

Erich Douglass


Here is the subclass of ArrayAdapter I'm using. Note that the objects I pass in has already been sorted alphabetically, with Collections.sort(objects).

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

    HashMap<String, Integer> sectionsMap = new HashMap<String, Integer>();
    ArrayList<String> sectionsList = new ArrayList<String>();

    ArrayList<Integer> sectionForPosition = new ArrayList<Integer>();
    ArrayList<Integer> positionForSection = new ArrayList<Integer>();

    public SectionIndexingArrayAdapter(Context context, int textViewResourceId,
            List<T> objects) {
        super(context, textViewResourceId, objects);

        // Note that List<T> objects has already been sorted alphabetically
        // e.g. with Collections.sort(objects) **before** being passed to
        // this constructor.

        // Figure out what the sections should be (one section per unique
        // initial letter, to accommodate letters that might be missing,
        // or characters like ,)
        for (int i = 0; i < objects.size(); i++) {
            String objectString = objects.get(i).toString();
            if (objectString.length() > 0) {
                String firstLetter = objectString.substring(0, 1).toUpperCase();
                if (!sectionsMap.containsKey(firstLetter)) {
                    sectionsMap.put(firstLetter, sectionsMap.size());
                    sectionsList.add(firstLetter);
                }
            }
        }

        // Calculate the section for each position in the list.
        for (int i = 0; i < objects.size(); i++) {
            String objectString = objects.get(i).toString();
            if (objectString.length() > 0) {
                String firstLetter = objectString.substring(0, 1).toUpperCase();
                if (sectionsMap.containsKey(firstLetter)) {
                    sectionForPosition.add(sectionsMap.get(firstLetter));
                } else
                    sectionForPosition.add(0);
            } else
                sectionForPosition.add(0);
        }

        // Calculate the first position where each section begins.
        for (int i = 0; i < sectionsMap.size(); i++)
            positionForSection.add(0);
        for (int i = 0; i < sectionsMap.size(); i++) {
            for (int j = 0; j < objects.size(); j++) {
                Integer section = sectionForPosition.get(j);
                if (section == i) {
                    positionForSection.set(i, j);
                    break;
                }
            }
        }
    }

    // The interface methods.

    public int getPositionForSection(int section) {
        return positionForSection.get(section);
    }

    public int getSectionForPosition(int position) {
        return sectionForPosition.get(position);
    }

    public Object[] getSections() {
        return sectionsList.toArray();
    }
}
like image 4
kinverarity Avatar answered Nov 15 '22 00:11

kinverarity


setFastScrollEnabled(true);

(http://developer.android.com/reference/android/widget/AbsListView.html)

like image 3
DHall Avatar answered Nov 15 '22 01:11

DHall


On anddev.org I found this tutorial: Alphabetic FastScroll ListView - similar to Contacts

It also contains a short demo-video

Hope it helps!

like image 2
Maaalte Avatar answered Nov 15 '22 01:11

Maaalte


To collect the details about the items shown in a listview, you can do this:

@Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {

            albumButton.setText(songs.get(firstVisibleItem).getAlbum());

        }

Isn't this a bit simpler? Here, 'songs' is an arraylist of Song objects. You can even get the last visible item by adding firstVisibleItem + visibleItemCount. I found this technique to be very useful. So then you would get the first letter of each song. I assume the gray box containing the letter in the music app you posted is a dialog box of sorts?

Anyway, hope this helps. I realise I'm late, but this is for future people

like image 2
TantrumV1 Avatar answered Nov 14 '22 23:11

TantrumV1