My task is keep expanded/collapsed groups during filter. I write own filter, which remove group if group don’t have any child left. But after groups is gone filter’s text is changed and group come back, but it will be collapsed.
So I save expand/collapse states to group objects. So I just need in right moment apply these states.
There is my try:
class SubjectGroupList extends ExpandableListView implements OnGroupCollapseListener, OnGroupExpandListener{
public SubjectGroupList(Context context) {
super(context);
}
public void onGroupExpand(int groupPos) {
SubjectGroup group = (SubjectGroup)getExpandableListAdapter().getGroup(groupPos);
group.expanded = true;
}
public void onGroupCollapse(int groupPos) {
SubjectGroup group = (SubjectGroup)getExpandableListAdapter().getGroup(groupPos);
group.expanded = false;
}
@Override
public void onFilterComplete(int count) {
fixCollapse();
super.onFilterComplete(count);
}
private void fixCollapse() {
Log.d("SubjectGroupList", "fix collapse");
SubjectGroupAdapter adapter = (SubjectGroupAdapter)getExpandableListAdapter();
int i = adapter.getGroupCount();
while (--i >= 0)
if (adapter.getGroup(i).expanded)
expandGroup(i);
else
collapseGroup(i);
}
}
but this don’t work at all. method onFilterComplete is never called.
I must find another way determine, when filter is apply before repainting.
Maybe anyone know? Thanks.
Edit:
My filter:
class GroupFilter extends Filter {
private SubjectGroupAdapter adapter;
public GroupFilter(SubjectGroupAdapter adapter) {
this.adapter = adapter;
}
@Override
protected FilterResults performFiltering(CharSequence s) {
FilterResults result = new FilterResults();
result.count = 0;
ArrayList<SubjectGroup> groups = new ArrayList<SubjectGroup>();
s = s.toString().toLowerCase();
for (SubjectGroup group : adapter.ori) {
SubjectGroup ng = new SubjectGroup(group.name, group.id);
int founded = 0;
for (SubjectItem item : group) {
if (s == null || s.length() == 0 || item.name.toLowerCase().contains(s)) {
ng.add(new SubjectItem(item.name, item.id));
result.count++;
founded++;
}
}
if (founded > 0)
groups.add(ng);
}
result.values = groups;
return result;
}
@Override
protected void publishResults(CharSequence s, FilterResults result) {
adapter.filter((ArrayList<SubjectGroup>) result.values);
}
}
*And method of adapter which accept filtered data *:
protected void filter(ArrayList<SubjectGroup> groups) {
this.groups = groups;
notifyDataSetInvalidated();
}
I founded answer.
I can register DataSetObserver to Adapter, who listens for data changes or invalidate. So I register observer in ExpandableListView by overriding addAdapter method:
Also I need tweak a bit Filter, because there was the mistakes.
It work very well. I hope someone else helps my experience.