1
votes

I'm trying to implement a listview that has fast scrolling with header previews. It looks like it's almost working correct, but I'm encountering some weird, bug-like behaviour. When I scroll down without using the fast scroll bar, the fast scroll bar disappears, and reappears only almost at the end. So there seems to be a gap or something like that.
My ListView's ArrayAdapter implements SectionIndexer and it's methods getSections(), getPositionForSection(int sectionIndex) and getSectionForPosition(int position). The getPositionForSection method is in my belief, the one causing trouble. When I log the value given by sectionIndex and I scroll down the list, this value exceeds the length of the actual sections (which is 20). This value comes from the SectionIndexer, not from myself. The Android refererence states:

If the section's starting position is outside of the adapter bounds, the position must be clipped to fall within the size of the adapter.

But when I clip the value to either 0 or section_size -1 (=19), the weird behaviour keeps appearing. Below is my ListView's ArrayAdapter implementing SectionIndexer. One note: the updateSections method is called from outside the adapter when the data changes in an AsyncTask. I hope someone knows what the problem is! Thanks in advance.

public class SoortArrayAdapter extends ArrayAdapter<Soort> implements SectionIndexer {
    List<Soort> data;
    private HashMap<String, Integer> alphaIndexer;
    private ArrayList<String> sections;
    public SoortArrayAdapter(@NonNull Context context, int resource, int textViewResourceId, List<Soort> data) {
        super(context, resource, textViewResourceId, data);
        this.data = data;
        sections = new ArrayList<>();
        alphaIndexer = new HashMap<String, Integer>();
    }

    private void updateSections() {
        alphaIndexer.clear();
        sections = new ArrayList<String>();
        for (int i = 0; i < data.size(); i++) {
            String s = data.get(i).getNaam().substring(0, 1).toUpperCase();
            if (!alphaIndexer.containsKey(s)) {
                alphaIndexer.put(s, i);
                sections.add(s);
            }
        }
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        if (convertView == null) {
            convertView = getLayoutInflater().inflate(android.R.layout.simple_list_item_1, parent, false);
        }

        TextView textView = convertView.findViewById(android.R.id.text1);
        textView.setText(data.get(position).getNaam());

        return convertView;
    }

    @Override
    public Object[] getSections() {

        return sections.toArray(new String[0]);
    }

    @Override
    public int getPositionForSection(int sectionIndex) {
        System.out.println(sectionIndex);
        if (sectionIndex >= sections.size()) {
            return 0;
        }
        System.out.println("position for section=" + sections.get(sectionIndex));
        return alphaIndexer.get(sections.get(sectionIndex));
    }

    @Override
    public int getSectionForPosition(int position) {
        String section = data.get(position).getNaam().substring(0, 1).toUpperCase();
        System.out.println("section for position=" + section);
        return alphaIndexer.get(section);
    }
}
1

1 Answers

0
votes

Looks like I misread the documentation for the above stated methods getSectionForPosition() and getPositionForSection(), especially for getSectionForPosition(). This made getPositionForSection() act strangely. I corrected my implementation, so the final implementation of the two methods is as follows:

    @Override
    public int getPositionForSection(int sectionIndex) {
        if (sectionIndex >= sections.size()) {
            return data.size() - 1;
        }

        if (sectionIndex < 0) {
            return 0;
        }

        return alphaIndexer.get(sections.get(sectionIndex));
    }

    @Override
    public int getSectionForPosition(int position) {
        String section = data.get(position).getNaam().substring(0, 1).toUpperCase();
        for (int i = 0; i < sections.size(); i++) {
            if (section.equals(sections.get(i))) {
                return i;
            }
        }
        return 0;
    }