ListView setOnItemClickListener ne fonctionne pas en ajoutant un bouton


89

J'ai une vue de liste avec du texte et un bouton dans chaque ligne, la vue de liste setOnItemClickListener () ne fonctionne pas. est-il possible de gérer différemment les événements de clic d'élément et de clic sur un bouton (le clic d'élément doit appeler ActivityA et le clic de bouton doit appeler ActivityB). Quelqu'un a-t-il une 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;
        }
    }
}`

Réponses:


260

Essayez de définir vos boutons (ou toute autre vue que vous souhaitez gérer en cliquant dans un élément de liste) comme ceci:

android:focusable="false"
android:focusableInTouchMode="false"

@Ben Lee: Je les ai ajoutés à mes cases à cocher! Ne fonctionne toujours pas. Que puis-je faire de mal?
TDaver

1
android:focusableInTouchMode="false"résout le mien. J'utilise deux TextView dans une ligne LinearLayout personnalisée. Yuk android ...
Youngjae

12
ImageButton ne fonctionnera pas. Dans la vue des éléments de liste contient ImageButton, définissez android: descendantFocusability = "blocksDescendants".
ChangUZ

8
l'ajout d'android: clickable = "false" peut également être requis (activez et désactivez-le dans le concepteur de mise en page pour l'ajouter explicitement au XML)
jrg

11
Avertissement: Si vous utilisez un ImageButton, vous devez utiliser setFocusable (false) car le constructeur de ImageButton activerait cet attribut après gonfler à partir du fichier xml. Mais bonne réponse
Mateu

118

Parfois, la liste ne pourra toujours pas faire passer l'écouteur de clic. Et dans ce cas, vous devrez peut-être ajouter un autre attribut.

android:descendantFocusability="blocksDescendants" 

Et cet attribut doit être ajouté à la mise en page la plus haute de votre XML où vous avez fourni les éléments ListView.


Juste pour que personne d'autre ne fasse ce que je viens de faire: ce ne sera pas souhaitable si vous avez quelque chose nécessitant du focus dans votre ligne comme un EditText. Je me sens stupide maintenant.
Kitalda

Dans mon cas, ce conseil a aidé. J'ai un TextView et un RadioButton, le 1er n'avait pas cliqué, le 2ème n'avait pas sélectionné TextView. J'ai écrit "android: clickable =" false "" dans RadioButton.
CoolMind

C'est la solution lorsque le bouton est un ImageButton
Mahonster

15

Si vous avez une vue active / une vue focalisable dans votre vue de liste, elle sera désactivée onItemClickListener... vous pouvez essayer de la rendre non focalisable en ajoutant: android:focusable="false"à toute vue qui est généralement focalisable.


8

Le truc de la pâte est d'ajouter à la fois Listenerà l'ensemble du rowViewet à l' Buttonintérieur Adapter. Quelque chose comme ça.

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();
    }
}

3
Comment est-ce encore mieux à distance? Vous créez un onClickListener pour CHAQUE élément de données par rapport à un seul auditeur. Votre exemple ne recycle même pas les vues.
JRomero

@ J.Romero ce n'était qu'un exemple, bien qu'il y ait beaucoup de place pour l'optimisation du code. Cependant, je viens de mettre à jour le code.
Adil Soomro

5

Essayez de mettre setClickable(false)pour chaque Button, ImageButton, etc et Viewcomme ceci:

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

Vous devez également ajouter

android:descendantFocusability="blocksDescendants"

à la disposition principale (premier niveau)


2
J'ai trouvé des blocs fixesLes descendants suffisent, pas besoin d'annuler le focusable etc. Android 4.1
djdance

2

Au lieu d'ajouter un bouton, ajoutez ImageViewet fournissez un setOnItemClcikécouteur qui fonctionnerait bien.

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;
}

1

J'obtiens également la même erreur. Si dans la mise en page de la liste vous avez un bouton pour le remplacer par TextViewie ImageButtonpar ImageView. Pour référence, c'est mon 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;
}

Gardez également à l'esprit de faire la mise en page de la liste au fur android:focussable="true"et à mesure de l'utilisation de ce bouton / paramètre de texte android:focussable="false".


corrigé, il devrait être android: focusable = "false" pas focussable
Kenny Dabiri

1

Ajoutez un android:focusable="false"attribut au bouton et à la vue parent, ajoutez un android:descendantFocusability="blocksDescendants"attribut comme celui-ci.

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

0

Il est étonnant de constater que la façon dont XML a changé provoque le setonitemclicked en java a fonctionné pour moi.

android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false"

0

Rendez l'attribut cliquable parent sur false comme ceci 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">

Encore une fois face au problème, puis pour toutes les vues enfants, ajoutez ce faux cliquable.


0

Je ne sais pas exactement pourquoi, mais parfois, lorsque vous définissez l'adaptateur, les auditeurs sont effacés. Ensuite, vous devez appeler setOnClickListeneraprès setAdapterou setListAdapter.


0

Supprimer android:clickable="true"de la vue personnalisée interne du ListView.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.