EDIT: Solution at bottom of post.
I am creating a contact screen for an android app where I want to be able to scroll through my phones contacts. I am able to import the phones contacts, use a custom arrayadapter to organize my information, and enable the fastscroll option for the listview. In addition, I am able to get the first letter of the current section to appear next to my thumb when I scroll. (i.e. if I am in the area where the names start with an A, it should show 'A' in the bubble next to my thumb which is scrolling).
My problem is that instead of showing the correct letter based on the current location, it shows 1 letter BEHIND where I am. For example, I am in the B section of contacts and it shows the letter 'A'. Any thoughts of what I am doing wrong?
Here is my adapter:
public class ContactAdapter extends ArrayAdapter<Contact> implements SectionIndexer {
Context context;
int layoutResourceId;
ArrayList<Contact> contacts = null;
private HashMap<String, Integer> alphaIndexer;
private String[] sections;
public ContactAdapter(Context context, int layoutResourceId, ArrayList<Contact> contacts) {
super(context, layoutResourceId, contacts);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.contacts = contacts;
Collections.sort(this.contacts);
alphaIndexer = new HashMap<String, Integer>();
for (int x = 0; x < this.contacts.size(); x++)
alphaIndexer.put(this.contacts.get(x).getSection(), x);
Set<String> sectionLetters = alphaIndexer.keySet();
ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
Collections.sort(sectionList);
sections = new String[sectionList.size()];
sectionList.toArray(sections);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Additional code here
}
static class ContactHolder {
TextView txtName;
CheckBox checked;
}
public int getPositionForSection(int section) {
return alphaIndexer.get(sections[section]);
}
public int getSectionForPosition(int position) {
return 0;
}
public Object[] getSections() {
return sections;
}
}
Here is the code that ended up making this work:
public ContactAdapter(Context context, int layoutResourceId, ArrayList<Contact> contacts) {
super(context, layoutResourceId, contacts);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.contacts = contacts;
this.results = new ArrayList<Contact>();
Collections.sort(this.contacts);
// Keys are the different sections, values are the indexes at which those sections start
alphaIndexer = new HashMap<String, Integer>();
// Only set the value for each key (section) when we encounter a new section
String prevSection = "";
for (int x = 0; x < this.contacts.size(); x++) {
String section = this.contacts.get(x).getSection();
if (!prevSection.equals(section)) {
alphaIndexer.put(section, x);
prevSection = section;
}
}
Set<String> sectionLetters = alphaIndexer.keySet();
ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
Collections.sort(sectionList);
sections = new String[sectionList.size()];
sectionList.toArray(sections);
}
Your implementation looks okay as far as I can see. I think there are two possibilities:
Contact.getSection()
method doesn't return the right value.If you can assure both things to be correct, please provide a screenshot of the error and a print
of your alphaIndexer
mapping.
Although not directly related to your question, you should rework your implementation of getSectionForPosition()
(sic!), since returning a constant may lead to an incorrect positioning of the scrollbar when swiping through your list (see here for further information).