Kevin Krumwiede
Kevin Krumwiede

Reputation: 10288

ExpandableListView does not call OnItemSelectedListener

I've set an OnItemSelectedListener in my custom ExpandableListView:

setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        Log.debug(TAG, "item selected");
        // do stuff
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        Log.debug(TAG, "nothing selected");
        // do stuff
    }           
});

This listener is never called, whether from touching items or calling setSelected(int) or setSelectedGroup(int).

There are other Q&As going back to 2010 about OnItemSelectedListener not working with ListView. I couldn't find one that actually explains how to get it working. The common answer is to use a click listener instead. I want to avoid that if possible, because I need to know when nothing is selected (i.e., the list is empty) and I want to take advantage of this feature of OnItemSelectedListener#onItemSelected(...):

This callback is invoked only when the newly selected position is different from the previously selected position or if there was no selected item.

I could achieve both of these things through other means, but it would be much nicer if OnItemSelectedListener worked.

Edit: It appears that ExpandableListView is completely broken with regard to item selection. When called in a click listener, this snippet logs the selected item as -1:

setSelection(0);
setSelectedGroup(0);
Log.debug(TAG, "selected item: " + getSelectedItemPosition());

Upvotes: 0

Views: 495

Answers (2)

Kevin Krumwiede
Kevin Krumwiede

Reputation: 10288

Using a click listener isn't just a lazy workaround. Thanks to some terrible design decisions, it's the only option. A blog post from 2008 explains why OnItemSelectedListener doesn't work:

In touch mode, there is no focus and no selection. Any selected item in a list of [sic] in a grid becomes unselected as soon as the user enters touch mode.

It continues:

The relationship between touch mode, selection, and focus means you must not rely on selection and/or focus to exist in your application. A very common problem with new Android developers is to rely on ListView.getSelectedItemPosition(). In touch mode, this method will return INVALID_POSITION.

The rationale for this is as follows:

Imagine a simple application . . . that shows a list of text items. The user can freely navigate through the list using the trackball and they can also scroll and fling the list using their finger. The issue in this scenario is the selection. If I select an item at the top of the list and then fling the list towards the bottom, what should happen to the selection? Should it remain on the item and scroll off the screen? In this case, what would happen if I then decide to move the selection with the trackball? Or worse, if I press the trackball to act upon the currently selected item, which is not shown on screen anymore. After careful considerations, we decided to remove the selection altogether.

<rant>In answering these questions, the Android devs ignored the conventions established by other UI toolkits and decades of user experience. When the list is scrolled, should the selection remain on the item? Yes, of course it should! What would happen if you moved the selection? The view would scroll to the new selection. And if you press the trackball? Act on the current selection!

Their "careful considerations" apparently didn't include where to put this crucial information, either. This belongs in the documentation for ListView, not in a blog post.</rant>

Upvotes: 1

Yogesh Nikam
Yogesh Nikam

Reputation: 633

Please use use one of following method which is suitable for you\

exlvReportData.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

        @Override
        public boolean onGroupClick(ExpandableListView parent, View v,
                                    int groupPosition, long id) {

            return false;
        }
    });

    // Listview Group expanded listener
exlvReportData.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {

        @Override
        public void onGroupExpand(int groupPosition) {
              //Toast.makeText(getApplicationContext(),
              //listDataHeader.get(groupPosition) + " Expanded",
              //Toast.LENGTH_SHORT).show();
        }
    });

    // Listview Group collasped listener
exlvReportData.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {

        @Override
        public void onGroupCollapse(int groupPosition) {
            //Toast.makeText(getApplicationContext(),
            //listDataHeader.get(groupPosition) + " Collapsed",
            // Toast.LENGTH_SHORT).show();

        }
    });

    // Listview on child click listener
    exlvReportData.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {

        @Override
        public boolean onChildClick(ExpandableListView parent, View v,
                                    int groupPosition, int childPosition, long id) {
            // TODO Auto-generated method stub
                 // Toast.makeText(
                 // getApplicationContext(),
                 // listDataHeader.get(groupPosition)
                 //  + " : "
                 // + listDataChild.get(
                 // listDataHeader.get(groupPosition)).get(
                 // childPosition), Toast.LENGTH_SHORT)
                 // .show();
            return false;
        }
    });

feel free for comment if you have any issue

Upvotes: 0

Related Questions