android fastScroll only covers part of the list
I have a class which implements expandable list activity
.
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.
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.
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)
精彩评论