1

I have a custom ListView item that has an ImageButton in it, and when I click it, the click events don't come through until the list item as a whole is interacted with, such as scrolling the list or tapping somewhere else on the list item. So for instance, if I click the ImageButton 5 times, nothing will happen, but then when I scroll the list, all 5 click events will come through simultaneously.

After a lot of research, I've come to find this is a common question, but none of the solutions I've found have worked for me so far. This question was quite helpful in learning some of the quirks of view interaction, and most other solutions I found used a similar approach to the accepted answer on that question, but unfortunately none of them worked for my particular situation.

So what I need to happen is to handle the click events for the ImageButton on the list item, as well as the click event for the list item itself. I've tried setting android:focusable="false" and android:focusableInTouchMode="false" on pretty much every view element involved in the display of this list. I've also tried setting these attributes programmatically. I also tried setting android:descendantFocusability="blocksDescendants" on several view elements including the ListView, the LinearLayout of the row item, and the CardView that contains all of this stuff.

The confusing part about all of this, is that I have this working just fine in another Activity of the same app. I have an ImageButton in a custom row layout of a ListView, and the onClick events work just fine for that. So it has to be something with my setup on this Activity. Here's some code:

The getView() of my custom BaseAdapter:

public View getView(int position, View convertView, ViewGroup parent) {
    FavoritesItemViewHolder favoriteItem = favoritesList.get(position);
    if(convertView == null) {
        convertView = favoriteItem.getNewConvertView(parent);
    } else {
        if(favoriteItem.getConvertView() == null) {
            convertView = favoriteItem.getNewConvertView(parent);
        } else {
            convertView = favoriteItem.getConvertView();
        }
    }

    return convertView;
}

The view inflation of my individual view holders:

public View getNewConvertView(ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.favorites_list_item, parent, false);

    TextView favoriteText = (TextView) convertView.findViewById(R.id.favoritesItemText);
    favoriteText.setText(itemTitle);

    //Here is where I'm setting the OnClickListeners for each row...
    ImageButton clearButton = (ImageButton) convertView.findViewById(R.id.favoritesClearButton);
    clearButton.setVisibility(View.VISIBLE);
    if(itemTitle.equals(context.getResources().getString(R.string.no_favorites))) {
        clearButton.setVisibility(View.INVISIBLE);
    } else {
        clearButton.setVisibility(View.VISIBLE);
        clearButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("CLEAR FAVORITE", "The clear button was just clicked on a favorites item...");
            }
        });
    }

    return convertView;
}

And here is the XML for my custom row layouts...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/favoritesListItemContainer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/favoritesItemText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:layout_gravity="center_vertical"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        android:layout_weight="0.9"/>

    <ImageButton
        android:id="@+id/favoritesClearButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_clear_x"
        android:layout_gravity="center_vertical"
        android:scaleType="centerInside"
        android:adjustViewBounds="true"
        android:background="@android:color/white"
        style="?android:attr/borderlessButtonStyle"
        android:layout_weight="0.1" />
</LinearLayout>

Any help would be appreciated. I'm just completely stumped here.

UPDATES


In this Activity, I'm using getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); in order to disable a SearchView and some other UI, and when the SearchView receives focus, suddenly my ListView items work as intended. So I'm guessing this has an issue with the ListView or the Window it's in having no focus, and so the click events don't come through until something on the screen receives focus.

What's strange is, when the keyboard is showing on the screen, I can click the list items and their ImageButtons and all the click events are handled correctly. But when I dismiss the keyboard, it breaks again.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
NoChinDeluxe
  • 3,446
  • 1
  • 16
  • 29

1 Answers1

0

There are known problems with ListView interfering with the touch events of views inside each item. You should switch to RecyclerView instead. ListView is seen as essentially deprecated for new apps with RecyclerView becoming its replacement.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • I was actually able to get this working by simply giving focus to the EditText inside my SearchView. Have no idea why that worked, but it did. But you are right, I should probably use RecyclerView, and that was something I was planning on implementing eventually anyway. Thanks for the input. – NoChinDeluxe Feb 08 '16 at 23:47
  • I encountered the exact same problem and workaround. In one project, I originally used a ListView because that's what I knew, then found it necessary over time to go all-in on RecyclerView because I hated all my workarounds. I hope you're able to convert soon! – Doug Stevenson Feb 08 '16 at 23:52