android fastScroll only covers part of the list
Asked Answered
M

2

19

I have a class which implements expandable list activity.
In the XML code (or I can do it in java), I set fastScrollEnabled to true. This does in deed enable fast scroll. BUT fast scroll only works in the top portion of the list. Like I can use the fastscroll thumb bar to scroll the whole list but only works in the top section of the scroll bar. It's not proportionate to the entire list. I can drag the thumb bar to the bottom of the list but it does no scrolling since the listview is already scrolled to the bottom due to the odd behaviour of it only working in the top portion of the list.
Confusing I know, I can try to clarify more if needed....

I do implement a custom BaseExpandableListAdapter.

Mutualism answered 16/12, 2010 at 14:31 Comment(2)
Are the rows in your list different sizes?Loch
can you.... please........ post your XMLMarquittamarr
N
5

I've just found a workaround to prevent the system to display this wrong behaviour.

There are two scenarios which use different code for the SectionIndexer to work.

The first scenario is the case that you use the FastScrollbar-Thumb to navigate to the next section. Assuming that the groups are your sections the overriden methods for implementing the SectionIndexer would look like that:

@Override
public int getPositionForSection(int section) {
    return section;
}

// Gets called when scrolling the list manually
@Override
public int getSectionForPosition(int position) {
    return ExpandableListView.getPackedPositionGroup(
               expandableListView
                   .getExpandableListPosition(position));
}

The second scenario is the case that you scroll the list manually and the fast scrollbars move according to the sections, not to all items. The code therefore looks like that:

@Override
public int getPositionForSection(int section) {
    return expandableListView.getFlatListPosition(
               ExpandableListView.getPackedPositionForGroup(section));
}

// Gets called when scrolling the list manually
@Override
public int getSectionForPosition(int position) {
    return ExpandableListView.getPackedPositionGroup(
               expandableListView
                   .getExpandableListPosition(position));
}

As one can see these two behaviours can not play together without further adoption.

The workaround to make it both work is to catch the case when someone is scrolling per hand (i.e. scrolling via touch). This can be done with implementing the OnScrollListener interface with the adapter class and set it onto the ExpandableListView:

public class MyExpandableListAdapter extends BaseExpandableListAdapter 
                 implements SectionIndexer, AbsListView.OnScrollListener {

    // Your fields here
    // ...
    private final ExpandableListView expandableListView;
    private boolean manualScroll;

    public MyExpandableListAdapter(ExpandableListView expandableListView
                                   /* Your other arguments */) {
        this.expandableListView = expandableListView;
        this.expandableListView.setOnScrollListener(this);
        // Other initializations
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        this.manualScroll = scrollState == SCROLL_STATE_TOUCH_SCROLL;
    }

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

    @Override
    public int getPositionForSection(int section) {
        if (manualScroll) {
            return section;
        } else {            
            return expandableListView.getFlatListPosition(
                       ExpandableListView.getPackedPositionForGroup(section));
        }
    }

    // Gets called when scrolling the list manually
    @Override
    public int getSectionForPosition(int position) {
        return ExpandableListView.getPackedPositionGroup(
                   expandableListView
                       .getExpandableListPosition(position));
    }

    // Your other methods
    // ...
}

That fixed the bug for me.

Nasia answered 16/12, 2010 at 14:32 Comment(2)
Wow, this fixed a bug we have had for 3 years. Thanks!It
@ mitch000001, I put your code in my ExpandableListView app, but it gave me a NullPointerException force close error whenever I expanded any group. Do I need the SectionIndexer.java in order to make it to work? Thank youHolleyholli
H
2

This is a bug in the fast scroller. It does not play well with ExpandableListView.

See my code.

(it also includes a work-around for some cases)

Hussy answered 29/4, 2012 at 12:47 Comment(1)
I downloaded your FastScroller.java, but I don't know how to impletement it. Can you guide me on how to impletement it in my ExpandableListView app? Thank you very much for the code.Holleyholli

© 2022 - 2024 — McMap. All rights reserved.