93 votes

ListView setOnItemClickListener ne fonctionne pas en ajoutant un bouton

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 traiter les événements de clic d'élément et de clic de bouton différemment (le clic d'élément devrait appeler l'activité A et le clic de bouton devrait appeler l'activité B). 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;
        }
    }
}`

261voto

Ben Lee Points 1328

Essayez de configurer vos boutons (ou toute autre vue que vous voulez gérer le clic dans un élément de liste) comme ceci :

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

0 votes

@Ben Lee : J'ai ajouté ces éléments à mes cases à cocher ! Cela ne fonctionne toujours pas. Qu'est-ce que je peux faire de mal ?

1 votes

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

0 votes

Quelqu'un a pu obtenir plus de détails sur les raisons de ce réglage ?

120voto

Andro Selva Points 24018

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

android:descendantFocusability="blocksDescendants" 

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

0 votes

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

0 votes

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

0 votes

Voici la solution lorsque le bouton est un ImageButton

15voto

nilesh Points 104

Si vous avez une vue active ou une vue focalisable dans votre vue de liste, cela désactivera les fonctions suivantes onItemClickListener ... vous pouvez essayer de le rendre non focalisable en ajoutant : android:focusable="false" à toute vue qui est habituellement focalisable.

8voto

Adil Soomro Points 18868

Le truc de la batterie est d'ajouter les deux Listener à l'ensemble de la rowView et à la Button à l'intérieur de 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 votes

En quoi est-ce un tant soit peu mieux ? Vous créez un onClickListener pour CHAQUE élément de données au lieu d'un seul listener. Votre exemple ne recycle même pas les vues.

0 votes

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

2voto

sharath yadhav Points 1

Au lieu d'ajouter le bouton ImageView et fournir setOnItemClcik qui fonctionnerait parfaitement.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X