Handle FastScroller behavior in Honeycomb and above
I'm not exactly sure what it's trying to accomplish.. but it was messing up the scrollbar before since getSectionForPosition was not implemented.
This commit is contained in:
parent
44897e85d2
commit
6d807c1455
@ -95,6 +95,10 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer, Libra
|
||||
* The section indexer, for the letter pop-up when scrolling.
|
||||
*/
|
||||
private final MusicAlphabetIndexer mIndexer;
|
||||
/**
|
||||
* The sections used by the indexer.
|
||||
*/
|
||||
private Object[] mSections;
|
||||
/**
|
||||
* True if this adapter should have a special MediaView with custom text in
|
||||
* the first row.
|
||||
@ -454,14 +458,23 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer, Libra
|
||||
@Override
|
||||
public Object[] getSections()
|
||||
{
|
||||
if (mSortMode != 0)
|
||||
return null;
|
||||
return mIndexer.getSections();
|
||||
if (mSections == null) {
|
||||
if (mSortMode == 0)
|
||||
mSections = mIndexer.getSections();
|
||||
else
|
||||
mSections = new String[] { " " };
|
||||
}
|
||||
return mSections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPositionForSection(int section)
|
||||
{
|
||||
if (section == 0)
|
||||
return 0;
|
||||
if (section == mSections.length)
|
||||
return getCount();
|
||||
|
||||
int offset = 0;
|
||||
if (mHasHeader) {
|
||||
if (section == 0)
|
||||
@ -474,8 +487,16 @@ public class MediaAdapter extends CursorAdapter implements SectionIndexer, Libra
|
||||
@Override
|
||||
public int getSectionForPosition(int position)
|
||||
{
|
||||
// never called by FastScroller
|
||||
return 0;
|
||||
if (mSortMode != 0)
|
||||
return 0;
|
||||
|
||||
if (mHasHeader) {
|
||||
if (position == 0)
|
||||
return 0;
|
||||
else
|
||||
position -= 1;
|
||||
}
|
||||
return mIndexer.getSectionForPosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,24 +16,162 @@
|
||||
|
||||
package org.kreed.vanilla;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import android.widget.AlphabetIndexer;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Handles comparisons in a different way because the Album, Song and Artist name
|
||||
* are stripped of some prefixes such as "a", "an", "the" and some symbols.
|
||||
* Like android.widget.AlphabetIndexer, but handles MediaStore sorting order
|
||||
* (strips "a", "the", etc).
|
||||
*/
|
||||
class MusicAlphabetIndexer extends AlphabetIndexer {
|
||||
public class MusicAlphabetIndexer {
|
||||
/**
|
||||
* The indexing sections.
|
||||
*/
|
||||
private static final String[] ALPHABET =
|
||||
{ " ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
|
||||
/**
|
||||
* The result of {@link MediaStore.Audio.keyFor(String)} called on each
|
||||
* letter of the alphabet.
|
||||
*/
|
||||
private static String[] ALPHABET_KEYS = null;
|
||||
/**
|
||||
* Cached section postions.
|
||||
*/
|
||||
private int mAlphaMap[];
|
||||
/**
|
||||
* Cursor that is used by the adapter of the list view.
|
||||
*/
|
||||
private Cursor mDataCursor;
|
||||
/**
|
||||
* The index of the cursor column that this list is sorted on.
|
||||
*/
|
||||
private int mColumnIndex;
|
||||
|
||||
/**
|
||||
* Constructs the indexer.
|
||||
*
|
||||
* @param sortedColumnIndex the column number in the cursor that is sorted
|
||||
* alphabetically
|
||||
*/
|
||||
public MusicAlphabetIndexer(int sortedColumnIndex)
|
||||
{
|
||||
super(null, sortedColumnIndex, " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
if (ALPHABET_KEYS == null) {
|
||||
String[] keys = new String[ALPHABET.length];
|
||||
for (int i = ALPHABET.length; --i != -1; ) {
|
||||
keys[i] = MediaStore.Audio.keyFor(ALPHABET[i]);
|
||||
}
|
||||
ALPHABET_KEYS = keys;
|
||||
}
|
||||
|
||||
mColumnIndex = sortedColumnIndex;
|
||||
mAlphaMap = new int[ALPHABET.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int compare(String word, String letter)
|
||||
/**
|
||||
* Returns the latin alphabet.
|
||||
*/
|
||||
public Object[] getSections()
|
||||
{
|
||||
String wordKey = MediaStore.Audio.keyFor(word);
|
||||
String letterKey = MediaStore.Audio.keyFor(letter);
|
||||
return wordKey.compareTo(letterKey);
|
||||
return ALPHABET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new cursor as the data set and resets the cache of indices.
|
||||
*
|
||||
* @param cursor the new cursor to use as the data set
|
||||
*/
|
||||
public void setCursor(Cursor cursor)
|
||||
{
|
||||
mDataCursor = cursor;
|
||||
Arrays.fill(mAlphaMap, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a binary search or cache lookup to find the first row that
|
||||
* matches a given section's starting letter.
|
||||
*
|
||||
* @param sectionIndex the section to search for
|
||||
* @return the row index of the first occurrence, or the nearest next letter.
|
||||
* For instance, if searching for "T" and no "T" is found, then the first
|
||||
* row starting with "U" or any higher letter is returned. If there is no
|
||||
* data following "T" at all, then the list size is returned.
|
||||
*/
|
||||
public int getPositionForSection(int sectionIndex) {
|
||||
Cursor cursor = mDataCursor;
|
||||
if (cursor == null)
|
||||
return 0;
|
||||
|
||||
if (sectionIndex <= 0)
|
||||
return 0;
|
||||
int count = cursor.getCount();
|
||||
if (sectionIndex >= ALPHABET.length)
|
||||
return count;
|
||||
|
||||
int pos = mAlphaMap[sectionIndex];
|
||||
if (pos != -1)
|
||||
return pos;
|
||||
|
||||
int savedCursorPos = cursor.getPosition();
|
||||
|
||||
int start = mAlphaMap[sectionIndex - 1];
|
||||
int end = count;
|
||||
if (start == -1)
|
||||
start = 0;
|
||||
|
||||
String targetLetter = ALPHABET_KEYS[sectionIndex];
|
||||
pos = (end + start) / 2;
|
||||
while (pos < end) {
|
||||
cursor.moveToPosition(pos);
|
||||
String curName = cursor.getString(mColumnIndex);
|
||||
String curLetter = MediaStore.Audio.keyFor(curName).substring(0, 3);
|
||||
int diff = curLetter.compareTo(targetLetter);
|
||||
if (diff != 0) {
|
||||
if (diff < 0) {
|
||||
start = pos + 1;
|
||||
if (start >= count) {
|
||||
pos = count;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
end = pos;
|
||||
}
|
||||
} else {
|
||||
// They're the same, but that doesn't mean it's the start
|
||||
if (start == pos) {
|
||||
// This is it
|
||||
break;
|
||||
} else {
|
||||
// Need to go further lower to find the starting row
|
||||
end = pos;
|
||||
}
|
||||
}
|
||||
pos = (start + end) / 2;
|
||||
}
|
||||
|
||||
mAlphaMap[sectionIndex] = pos;
|
||||
cursor.moveToPosition(savedCursorPos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section index for a given position in the list by querying the item
|
||||
* and comparing it with all items in the section array.
|
||||
*/
|
||||
public int getSectionForPosition(int position)
|
||||
{
|
||||
int savedCursorPos = mDataCursor.getPosition();
|
||||
mDataCursor.moveToPosition(position);
|
||||
String key = MediaStore.Audio.keyFor(mDataCursor.getString(mColumnIndex));
|
||||
mDataCursor.moveToPosition(savedCursorPos);
|
||||
|
||||
String[] alphabet = ALPHABET_KEYS;
|
||||
for (int i = 1, len = alphabet.length; i != len; ++i) {
|
||||
if (key.startsWith(alphabet[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user