ExpandableListView tiered items are not always clickable

I made the usual 3-level ExpandableListView, based on many examples on the Internet, and it works well.

With one caveat. Clicking on the 2nd and 3rd levels does not always work. Although sometimes it works fine. Usually it runs everywhere at startup. Then it no longer works like 50% of items. Without any logic. Sometimes I expand the second group, and then I can no longer destroy this group. Or sometimes I expand the second group, and then I cannot collapse any other group of the second level. The only consistent thing is that it is often fixed by scrolling through the locked view from the visible area and vice versa.

What could be?

    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"
        />

how it looks

https://code.google.com/p/android/issues/detail?id=3414, ( ), . ( , ). logcat,

, , , - onMeasure. . , 1- , 2- ?

+4
3

, , hasStableIds true, getGroupId getChildId . , ExpandableListView. hasStableIds true , .

+1

getChildView getGroupView

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);



        cache.put(groupPosition*10000 + childPosition, l);
        l.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Log.d("LibraryListAdapter"," group clicked :  " + groupPosition + "childClicked :" + childPosition);

                    }
                });
        return l;
    }

    @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));

        row.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Log.d("LibraryListAdapter"," group clicked :  " + groupPosition);

                    }
                });
        return row;
    }
}



public class LibraryListCityAdapter extends LibraryListBaseAdapter
{

    @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"));
        row.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Log.d("LibraryListCityAdapter"," group clicked :  " + groupPosition + " childClicked :" + childPosition);


                    }
                });
        return row;
    }


    @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));
        rowsetText(localLibs.get(state).get(city).get(childPosition).get("NAME"));
        row.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Log.d("LibraryListCityAdapter"," group clicked :  " + groupPosition );


                    }
                });
        return row;
    }

}

, , getGroupView getChildView setOnChildClickListener Listview

+1

, . .

Try using a library called FloatingGroupExpandableListView , which is much better than an extensible list.

Using this, you need less code, and it also changes the color of the group when the group view was reduced during scrolling.

-1
source

All Articles