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:
Is there a method to enable functionality like this in a ListView
in the Android SDK?
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.
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();
}
}
setFastScrollEnabled(true);
(http://developer.android.com/reference/android/widget/AbsListView.html)
On anddev.org I found this tutorial: Alphabetic FastScroll ListView - similar to Contacts
It also contains a short demo-video
Hope it helps!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With