ListView setOnItemClickListener not working by adding button
Asked Answered
P

12

93

I have a list view with text and button in each row, list view setOnItemClickListener() is not working. is it possible to handle item click and button click events differently(item click should call ActivityA and button click should call ActivityB). Does anyone have a solution

    private ArrayList<String> userIDArr = null;
    private ArrayList<String> userNameArr = null;
    private DatabaseHelper dbHelper = null;
    private ListView userListView=null; 


    public void onCreate(Bundle savedInstanceState) 
        {
          super.onCreate(savedInstanceState);         
          setContentView(R.layout.list_view);         
          dbHelper = new DatabaseHelper(this.getApplicationContext());        
          Map<String,ArrayList<String>> displayMap = dbHelper.getUserListToDisplay();
          userIDArr = displayMap.get("UserID");
          userNameArr = displayMap.get("FirstName1");           


          userListView = (ListView) findViewById(R.id.listView2);
          userListView.setAdapter(new UserListAdapter(this,userIDArr));


          userListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
              @Override
              public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {

                  Toast.makeText(usersListActivity.this,
                            "Item in position " + position + " clicked", Toast.LENGTH_LONG).show();
              }
            });
     }


    public class UserListAdapter extends ArrayAdapter<String>
    {
        Activity context;
        public UserListAdapter(Activity context, ArrayList<String> names) {
            super(context, R.layout.list_item, names);
            this.context = context;
        }
        private class ViewHolder {
            public TextView UserNameAndID;
            public TextView Description;
            public Button  UploadBtn;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            View rowView = convertView;
            if (rowView == null) {
                LayoutInflater inflater = context.getLayoutInflater();
                rowView = inflater.inflate(R.layout.list_item, null, true);
                holder = new ViewHolder();
                holder.UserNameAndID = (TextView) rowView.findViewById(R.id.User_detailsTxt);
                holder.Description = (TextView) rowView.findViewById(R.id.User_status);
                holder.UploadBtn = (Button) rowView.findViewById(R.id.uploadbutton);
                holder.UploadBtn.setOnClickListener(new View.OnClickListener() {  

                        public void onClick(View v) {  
                        Toast.makeText(usersListActivity.this," Button clicked",Toast.LENGTH_SHORT).show();
                        }   
                    }); 
                    rowView.setTag(holder);
            } else {
                holder = (ViewHolder) rowView.getTag();
            }
            String s = userNameArr.get(position)+","+userIDArr.get(position);
            holder.UserNameAndID.setText(s);
            holder.Description.setText("U r in middle");
            return rowView;
        }
    }
}`
Pomeranian answered 15/7, 2011 at 6:19 Comment(0)
P
261

Try setting your buttons (or any other views you want to handle click inside a list item) like this:

android:focusable="false"
android:focusableInTouchMode="false"
Phonologist answered 15/7, 2011 at 7:7 Comment(12)
@Ben Lee: I added these to my checkboxes! Still not working. What can I be doing wrong?Impale
android:focusableInTouchMode="false" solves mine. I use two TextView in a custom LinearLayout row. Yuk android...Espouse
Someone get more details why setting like this?Nasturtium
ImageButton will not work. In list item view contains ImageButton, set android:descendantFocusability="blocksDescendants".Showker
adding android:clickable="false" can also be required (toggle it on, and off, in the layout designer to get it explicitly added to the XML)Crofoot
Saved me too. Any idea on why is ListView acting like this?Flammable
android:setselectable and android:setclickable should be set to "false"Appling
finally - fully customized listView, both single and multi choice managed by widget! but i'm still really wonder - how it works and why do we need to set focusable?Angstrom
Warning: In case that you are using a ImageButton you need to use setFocusable(false) cause the constructor of ImageButton would enabe this attribute after inflate from xml file. But good answer thoughCarillonneur
Good call, this worked with a custom item composed of two textviews and an imageView.Unthinking
this works, but for that the property android: clickable must be false for the "view" in question. Attention to the parents of the "View" to be not using "android: clickable" on. this will block the pattern selector of your list or derivative. You can match the pattern selector with a custom selector using the property android: foreground like this: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:fitsSystemWindows="true"> <FrameLayout "android: foreground="CUSTOM SELECTOR""> <RelativeLayout><RelativeLayout/> <.../> <.../>Felic
Yes it works with above attributes without setting clickable attribute.Cultch
S
122

Sometimes the List will still not be able to make the Click Listener to pass. And at this case you might have to add one more attribute.

android:descendantFocusability="blocksDescendants" 

And this attribute has to be added to the top most layout of your XML where you have provided the ListView elements.

Shayneshays answered 11/12, 2012 at 10:7 Comment(4)
Just so no-one else does what I just did: This will be undesirable if you have something requiring focus in your row like an EditText. I feel stupid now.Right
In my case this advice has helped. I have a TextView and RadioButton, the 1st hadn't clicked, the 2nd hadn't select the TextView. I wrote "android:clickable="false"" in RadioButton.Thumbsdown
This is the solution when the button is an ImageButtonTherontheropod
Curiously, this solution worked for me. The OnItemClickListener works without affecting the descendant events. Not sure why it worked, so... go figure.Continuous
H
15

If you have an active view/focusable view in your list view then it will disable onItemClickListener... you can try to make it unfocusable by adding: android:focusable="false" to any view that is usually focusable.

Helle answered 16/1, 2012 at 9:26 Comment(0)
S
8

Batter thing is to add both Listener to the whole of the rowView and to the Button inside Adapter. Something like this.

public class MyAdapter extends BaseAdapter implements View.OnClickListener{

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
            View rowView = convertView;
            if(rowView == null)
            {
                    //intialize rowView, and set onclick listener only once.
                    rowView = someIntilizationMehhodOrInflatorMethod();
                    //add listener to the button also and also to the row view
                    rowView.setOnClickListener(this);
            }
            //all your inflation and setting values goes here and at the end,
            //set position as tag to get the correct position, rather buggy one.
            rowView.setTag(String.valueOf(position));


            return rowView;
    }
    public void onClick(View v)
    {
            //now get the tag of View v and convert it to integer.
            int pos = Integer.parseInt(v.getTag().toString());
            Toast.makeText(context,"Item in position " + pos + " clicked",Toast.LENGTH_LONG).show();
    }
}
Strobe answered 15/7, 2011 at 6:51 Comment(2)
How is this even remotely better? You are creating an onClickListener for EVERY data element vs only 1 listener. You're example doesn't even recycle which views.Billfold
@J.Romero this was just an example, although there is loot of room for code optimization. However I've just updated the code.Strobe
S
5

Try set setClickable(false) for each Button, ImageButton, etc and View like this:

view.setClickable(false);
button.setClickable(false);
imagebutton.setClickable(false);

Also you have to add

android:descendantFocusability="blocksDescendants"

to main(first level) layout

Swink answered 18/7, 2016 at 20:46 Comment(1)
I've found set blocksDescendants is enough, no need to cancel focusable etc. Android 4.1Averell
G
2

Instead of adding button add ImageView and provide setOnItemClcik listener which would work fine.

public View getView(final int position, View convertView, ViewGroup parent) {
     MyViewHolder mViewHolder;
     if(convertView == null) {
         convertView = inflater.inflate(R.layout.youtubesearchrow, null);
         mViewHolder = new MyViewHolder();
         mViewHolder.alarm = (ImageView)convertView.findViewById(R.id.alarm);
         convertView.setTag(mViewHolder);
     } else {
         mViewHolder = (MyViewHolder) convertView.getTag();
     }

     mViewHolder.tvTitle = detail(convertView, R.id.tvTitle,    
     // mViewHolder.tvDesc  = detail(convertView, R.id.tvDesc,  
     mViewHolder.ivIcon  = detail_image(convertView, R.id.ivIcon,  

     mViewHolder.alarm.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
        // TODO Auto-generated method stub
        }
    });

        return convertView;
}
Glarus answered 7/9, 2014 at 18:26 Comment(0)
G
1

I'm also getting the same error. If in the list layout you have any button to replace it with TextView i.e ImageButton with ImageView. For Reference their is my code:

private Activity activity;
private LayoutInflater inflater;

private List<ItemList> itemListsItems;

private Bookmark_SharedPref pref;

ImageLoader imageLoader = AppController.getInstance().getImageLoader();

public CustomListAdapter_Item(Activity activity,List<ItemList> itemListsItems){
    this.activity=activity;
    this.itemListsItems=itemListsItems;
    pref = new Bookmark_SharedPref(activity);
}


@Override
public int getCount() {
    return itemListsItems.size();
}

@Override
public Object getItem(int position) {
    return itemListsItems.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View v = convertView;
    ViewHolder holder;

    if(inflater == null){
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    if(convertView == null){
        convertView = inflater.inflate(R.layout.item_layout,null);

        holder = new ViewHolder();
        convertView.setTag(holder);
    }
    else{
        holder = (ViewHolder)convertView.getTag();
    }


    if(imageLoader == null){
        imageLoader = AppController.getInstance().getImageLoader();
    }




     holder.img = (NetworkImageView)convertView.findViewById(R.id.item_image);
    holder.Title = (TextView)convertView.findViewById(R.id.item_title);
    holder.Cat = (TextView)convertView.findViewById(R.id.item_category);

    holder.id = (TextView)convertView.findViewById(R.id.itemid);

    holder.Desc = (TextView)convertView.findViewById(R.id.item_description);

    holder.book = (ImageView)convertView.findViewById(R.id.bookmark_star);



    // getting blog data or the row
    ItemList il = itemListsItems.get(position);

    //setting image
    holder.img.setImageUrl(il.getImageUrl(), imageLoader);

    // setting title
    holder.Title.setText(il.getTitle());

    //setting category
    holder.Cat.setText(il.getCategory());


    //setting blog id
    holder.id.setText(il.getId());

    //setting description
    holder.Desc.setText(il.getDescription());

    //bookmarking the post
    holder.book.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            itemListsItems.get(position).isFav = !itemListsItems.get(position).isFav;
            ((ImageView)v.findViewById(R.id.bookmark_star)).setImageResource(itemListsItems.get(position).isFav ? R.mipmap.active_star : R.mipmap.inactive_star);

            if(itemListsItems.get(position).isFav){
                String data = Integer.toString(itemListsItems.get(position).id);
                Toast.makeText(v.getContext(),"fav hai "+data,Toast.LENGTH_SHORT).show();
                pref.addPref(data);
            } else {
                String data = Integer.toString(itemListsItems.get(position).id);
                Toast.makeText(v.getContext(),"not fav"+ data,Toast.LENGTH_SHORT).show();
                pref.removePref(data);
            }
            //notifyDataSetChanged();
        }
    });

    ((ImageView)convertView.findViewById(R.id.bookmark_star)).setImageResource(itemListsItems.get(position).isFav ? R.mipmap.active_star : R.mipmap.inactive_star);

    /*
    if(itemListsItems.get(position).isFav){
        String data = Integer.toString(itemListsItems.get(position).id);
        Toast.makeText(convertView.getContext(),"fav hai "+data,Toast.LENGTH_SHORT).show();
        pref.addPref(data);
    } else {
        String data = Integer.toString(itemListsItems.get(position).id);
        //Toast.makeText(convertView.getContext(),"not fav"+ data,Toast.LENGTH_SHORT).show();
        pref.removePref(data);
    }
    */
    return convertView;
}

private static class ViewHolder {
   public TextView Title, Desc,Cat,id;
    ImageView book;
    NetworkImageView img;
}

Also keep in mind to make list layout as android:focussable="true" and for that button/text parameter use android:focussable="false".

Grory answered 31/12, 2015 at 9:49 Comment(1)
corrected it should be android:focusable="false" not focussableStaminody
A
1

Make the parent clickable attribute to false like this android:clickable="false".

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="false"
    android:orientation="vertical">

Again facing problem, then for all the child views add this clickable false.

Aerography answered 20/10, 2017 at 9:42 Comment(0)
M
1

Add android:focusable="false" attribute to button and to parent view add android:descendantFocusability="blocksDescendants" attribute like this.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:descendantFocusability="blocksDescendants">

    <ImageButton
        android:id="@+id/sell_button"
        android:layout_width="wrap_content"
        android:focusable="false"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_sell" />
</RelativeLayout>
Moil answered 28/7, 2018 at 13:25 Comment(0)
E
1

It's amazing to noticed that how XML changed causes the setonitemclicked in java Worked for me..

android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false"
Exportation answered 16/12, 2019 at 22:51 Comment(0)
B
0

I don't know exactly why, but sometimes when you set the adapter, the listeners are cleared. Then, you must call setOnClickListener after setAdapter or setListAdapter.

Baptist answered 18/2, 2015 at 17:20 Comment(0)
C
0

Remove android:clickable="true" from the internal custome view from the ListView.

Cide answered 15/8, 2016 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.