ExpandableListView expand only on a specific Butto

2020-02-26 06:34发布

问题:

well i´m trying to create a ExpandableListView like Spotify it does... But i don´t have any idea how do disable the LinearLayout to act like a button (Expand the list) I have created a image which should describe what i like. I like to have the possibility to handle a click on the text / image (parent) as a normal interaction. A click on the right button should expand the list like in Spotify...

回答1:

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.

@Override
public 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.

@Override
public 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! ;)



回答2:

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...



回答3:

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;
}
....
@Override
public 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);