I made an usual 3-level ExpandableListView based on the many examples on the internet and it works well.
With one caveat. Clicking on the 2nd and 3rd level does not work always. Although sometimes it works fine. Usually at start it works everywhere. Then it does not work anymore, on like 50% of the items. Without any logic. Sometimes I expand a 2nd group and then I cannot collapse that group anymore. Or sometimes I expand a 2nd group and then I cannot collapse any other group of the 2nd level. The only consistent thing is that it often gets fixed by scrolling the locked up view out of the visible area and back in.
What could be going on?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chooselib);
//...
ExpandableListView lv = (ExpandableListView) findViewById(R.id.libListView);
lv.setAdapter(new LibraryListAdapter());
}
final List<String> states = new ArrayList<String>();
final List<List<String>> cities = new ArrayList<List<String>>();
final List<List<List<Map<String, String>>>> localLibs = new ArrayList<List<List<Map<String, String>>>>();
public abstract class LibraryListBaseAdapter extends BaseExpandableListAdapter{ //changing these functions has no effect whatsoever on the problem
@Override
public Object getChild(int groupPosition, int childPosition)
{
return getChildId(groupPosition, childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition)
{
return (groupPosition << 15) + childPosition + 1;
}
@Override
public Object getGroup(int groupPosition)
{
return getGroupId(groupPosition);
}
@Override
public long getGroupId(int groupPosition)
{
return (groupPosition << 15);
}
@Override
public boolean hasStableIds()
{
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition)
{
return true;
}
}
public class LibraryListAdapter extends LibraryListBaseAdapter
{
Map<Integer, ExpandableListView> cache = new TreeMap<Integer, ExpandableListView>();
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
if (cache.containsKey(groupPosition*10000 + childPosition))
return cache.get(groupPosition*10000 + childPosition);
LibraryListCityView l = new LibraryListCityView();
l.setPadding((int)(60 * getResources().getDisplayMetrics().density), l.getPaddingTop(), l.getPaddingRight(), l.getPaddingBottom());
//l.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); has no effect whatsoever
//l.setFocusable(true); has no effect whatsoever
l.setAdapter(new LibraryListCityAdapter(groupPosition,childPosition));
if (cities.get(groupPosition).size() == 1) l.expandGroup(0);
l.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int lib, long l) {
onLeafClick(groupPosition,childPosition,lib);
return false;
}
});
cache.put(groupPosition*10000 + childPosition, l);
return l;
}
@Override
public int getChildrenCount(int groupPosition)
{
return cities.get(groupPosition).size();
}
@Override
public int getGroupCount()
{
return states.size();
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent)
{
View row = //convertView != null && convertView instanceof TextView ? convertView :
getLayoutInflater().inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
((TextView) row).setText(states.get(groupPosition));
return row;
}
}
public class LibraryListCityView extends ExpandableListView
{
int intGroupPosition, intChildPosition, intGroupid;
public LibraryListCityView()
{
super(LibraryList.this);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST); //what does this do?
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//from http://stackoverflow.com/questions/19298155/issue-with-expanding-multi-level-expandablelistview
@Override
protected void onDetachedFromWindow() {
try {
super.onDetachedFromWindow();
} catch (IllegalArgumentException e) {
// TODO: Workaround for http://code.google.com/p/android/issues/detail?id=22751
}
}
}
public class LibraryListCityAdapter extends LibraryListBaseAdapter
{
int state,city;
LibraryListCityAdapter (int a, int b) {
state = a;
city = b;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent)
{
//todo: use convertView (but do not want to mix groupView/childView up)
View row = getLayoutInflater().inflate(R.layout.libraryinlistview , parent, false);
((TextView) row).setText(localLibs.get(state).get(city).get(childPosition).get("NAME"));
return row;
}
@Override
public int getChildrenCount(int groupPosition)
{
return localLibs.get(state).get(city).size();
}
@Override
public int getGroupCount()
{
return 1;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent)
{
View row = getLayoutInflater().inflate(R.layout.librarycityinlistview, parent, false);
((TextView) row).setText(cities.get(state).get(city));
return row;
}
}
chooselib.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lay_chooselib_choose"
android:id="@+id/textView" android:layout_gravity="center_vertical|left" android:padding="5sp"/>
<ExpandableListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/libListView" android:layout_gravity="right|center_vertical"
/>
</LinearLayout>
librarycityinlistview.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
/>
libraryinlistview.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingLeft="60dip"
android:gravity="center_vertical"
/>
Sounds a little like https://code.google.com/p/android/issues/detail?id=3414 but kind of is the opposite (since the problematic list is an item to the outer list view), and changing descand focusability did not change anything. (since only textviews are in the list they are not focusable anyways). And nothing useful in the logcat, too
What I do not really understand of the source I based on is the stuff in onMeasure. And the split between the groups and children of the listviews. Perhaps it is better to have an expandable list view for every group on the 1st level, instead one for every group on the 2nd level?