ExpandableListView expand only on a specific Button? ExpandableListView expand only on a specific Button? android android

ExpandableListView expand only on a specific Button?


This is a bit old question, but this answer might help someone.

If you want to expand/collapse group by clicking on specific Button or some other View, you have to get that Button in getGroupView method in your Adapter class. Then, in onClick method of your Button you have, either to cast parent to ExpandableListView, or to pass List's reference in constructor when you create adapter.

I prefer the first approach. Here's the code, assuming that you have one TextView and an ImageView that is the arrow. I've added changing the arrow state too.

@Overridepublic View getGroupView(final int groupPosition, final boolean isExpanded,        View convertView, final ViewGroup parent) {    String headerTitle = (String) getGroup(groupPosition);    if (convertView == null) {        LayoutInflater infalInflater = (LayoutInflater) context                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);        convertView = infalInflater.inflate(R.layout.left_drawer_list_group, parent, false);    }    TextView listHeaderText = (TextView) convertView            .findViewById(R.id.left_menu_list_header_text);    ImageView listHeaderArrow = (ImageView) convertView.findViewById(R.id.left_menu_list_header_arrow);    listHeaderText.setText(headerTitle);    //Set the arrow programatically, so we can control it    int imageResourceId = isExpanded ? android.R.drawable.arrow_up_float : android.R.drawable.arrow_down_float;    listHeaderArrow.setImageResource(imageResourceId);    listHeaderArrow.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            if(isExpanded) ((ExpandableListView) parent).collapseGroup(groupPosition);            else ((ExpandableListView) parent).expandGroup(groupPosition, true);        }    });    return convertView;}

Additionally, you would like to disable expanding/collapsing in onGroupClick listener.

@Overridepublic boolean onGroupClick(ExpandableListView parent, View v,        int groupPosition, long id) {    //Do some other stuff, but you shall not expand or collapse    return true;}

There is another method, but the fairly bad one, and that is that you copy entire Adapter class inside the class where you create ExpandableListView and set Adapter. But do not do that. Seriously! ;)


This is the onCreate from the ChannelList which extends ListFragment. It stores the data and generate a new Adapter if the Fragment is called.

@Override   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {                                   m_ListView = new ExpandableListView(getActivity());    m_ListView.setId(android.R.id.list);    m_ListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);    m_ListView.setMultiChoiceModeListener(m_MultiChoiceModeListener);    m_ChannelListAdapter = new ChannelListAdapter(getActivity(), this);    m_ListView.setAdapter(m_ChannelListAdapter);    m_ListView.setGroupIndicator(null);    m_ListView.setOnGroupClickListener(this);    return m_ListView;}

On the Adapter i have the getGroupView Method which look like:

public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {    if (view == null)     {        view = inflater.inflate(R.layout.layout_channelwithimage, viewGroup, false);    }    TextView textView = (TextView) view.findViewById(R.id.labelwithimage);    textView.setText(getGroup(i).toString());    ImageButton imbu = (ImageButton) view.findViewById(R.id.imageButton);    //imbu.setOnClickListener(this);        imbu.setFocusable(false);    return view;}

So if i register the ImageButton in the adapter it will call the onClick from the adapter. But in the onClick i do not know which group was clicked... If i do not register the button on any listener it will not call the onGroupClick from the ChannelList...


Not overly elegant solution but it helped me out:

I've preserved the original groupIndicator. I liked the behavior as it was.

On the groupItem layout I simply blocked the space with empty view so that the original groupIndicator was still clickable:

<LinearLayout> ....<!--just dummy space underneath the default expand_collapse group icon - this way original expand collapse behavior is preserved on the icon--><View        android:layout_width="25dp"        android:layout_height="match_parent"></View><!-- text view will have actionListener --><TextView        android:id="@+id/category_name"        android:layout_weight="1"        android:layout_width="0dp"        android:layout_height="match_parent"        .... /> .... </LinearLayout>

Than sneaked in callBack object while creating ExpandableListAdapter and hooked it onClick on the "category_name" (for both child and group elements)

public class ExpandableListAdapter extends BaseExpandableListAdapter {public interface OnCategoryActionListener {    boolean onCategorySelected(long categoryId);}....public ExpandableListAdapter(Activity context, Category rootCategory,    OnCategoryActionListener callBack) {    this.context = context;    this.rootCategory = rootCategory;         this.callBack = callBack;}....@Overridepublic View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {    String categoryName = (String) getGroup(groupPosition);    if (convertView == null) {        LayoutInflater inflater = (LayoutInflater)             context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        convertView = inflater.inflate(R.layout.category, null);    }    TextView item = (TextView) convertView.findViewById(R.id.category_name);    item.setTypeface(null, Typeface.BOLD);    item.setText(categoryName);    item.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View view) {            callBack.onCategorySelected(getGroupId(groupPosition));        }    });  .....

All you have to do now is to initialize properly ExpandableListAdapter in master fragment class

expListAdapter = new ExpandableListAdapter(getActivity(), this.rootCategory,         new OnCategoryActionListener());expListView = (ExpandableListView) getActivity().findViewById(R.id.categories_list);expListView.setAdapter(expListAdapter);