182 votes

Android : Éléments ListView avec plusieurs boutons cliquables

J'ai un ListView où chaque élément de la liste contient un TextView et deux Boutons différents. Quelque chose comme ceci :

ListView
--------------------
[Text]
[Button 1][Button 2]
--------------------
[Text]
[Button 1][Button 2]
--------------------
... (and so on) ...

Avec ce code, je peux créer un OnItemClickListener pour l'ensemble de l'article :

listView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> list, View view, int position, long id) {
        Log.i(TAG, "onListItemClick: " + position);

        }

    }
});

Cependant, je ne veux pas que l'ensemble de l'élément soit cliquable, mais seulement les deux boutons de chaque élément de liste.

Ma question est donc la suivante : comment puis-je mettre en œuvre un onClickListener pour ces deux boutons avec les paramètres suivants :

  • int button (quel bouton de l'élément a été cliqué)
  • int position (qui est l'élément de la liste sur lequel le clic du bouton s'est produit)

Mise à jour : J'ai trouvé une solution comme décrite dans ma réponse ci-dessous. Maintenant, je peux cliquer/taper sur le bouton via l'écran tactile. Cependant, je ne peux pas le sélectionner manuellement avec la boule de commande. Il sélectionne toujours l'élément entier de la liste et de là passe directement à l'élément suivant de la liste en ignorant les boutons, même si j'ai réglé la fonction .setFocusable(true) y setClickable(true) pour les boutons dans getView() .

J'ai également ajouté ce code à mon adaptateur de liste personnalisé :

@Override
public boolean  areAllItemsEnabled() {
    return false;           
}

@Override
public boolean isEnabled(int position) {
        return false;
}

Cela fait qu'aucun élément de la liste n'est plus sélectionnable du tout. Mais cela n'a pas aidé à rendre les boutons imbriqués sélectionnables.

Quelqu'un a une idée ?

150voto

znq Points 13027

La solution à ce problème est en fait plus simple que je ne le pensais. Vous pouvez simplement ajouter dans votre adaptateur personnalisé la fonction getView() un setOnClickListener() pour les boutons que vous utilisez.

Toute donnée associée au bouton doit être ajoutée avec myButton.setTag() dans le getView() et est accessible dans le onClickListener via view.getTag()

J'ai posté une solution détaillée sur mon blog comme un tutoriel.

62voto

greg7gkb Points 1625

C'est une sorte d'appendice de la réponse de @znq...

Il existe de nombreux cas où vous souhaitez connaître la position de la rangée pour un élément cliqué ET vous souhaitez savoir quelle vue de la rangée a été touchée. Cela va devenir beaucoup plus important dans les interfaces utilisateur pour tablettes.

Vous pouvez le faire avec l'adaptateur personnalisé suivant :

private static class CustomCursorAdapter extends CursorAdapter {

    protected ListView mListView;

    protected static class RowViewHolder {
        public TextView mTitle;
        public TextView mText;
    }

    public CustomCursorAdapter(Activity activity) {
        super();
        mListView = activity.getListView();
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // do what you need to do
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = View.inflate(context, R.layout.row_layout, null);

        RowViewHolder holder = new RowViewHolder();
        holder.mTitle = (TextView) view.findViewById(R.id.Title);
        holder.mText = (TextView) view.findViewById(R.id.Text);

        holder.mTitle.setOnClickListener(mOnTitleClickListener);
        holder.mText.setOnClickListener(mOnTextClickListener);

        view.setTag(holder);

        return view;
    }

    private OnClickListener mOnTitleClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Title clicked, row %d", position);
        }
    };

    private OnClickListener mOnTextClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Text clicked, row %d", position);
        }
    };
}

22voto

Fabricio PH Points 675

Pour les futurs lecteurs :

Pour sélectionner manuellement les boutons avec la boule de commande, utilisez :

myListView.setItemsCanFocus(true);

Et pour désactiver le focus sur l'ensemble des éléments de la liste :

myListView.setFocusable(false);
myListView.setFocusableInTouchMode(false);
myListView.setClickable(false);

Il fonctionne bien pour moi, je peux cliquer sur les boutons avec l'écran tactile et permet également de se concentrer et de cliquer en utilisant le clavier.

12voto

Bhavin Chauhan Points 472

Je n'ai pas beaucoup d'expérience que les utilisateurs ci-dessus, mais j'ai été confronté à ce même problème et je l'ai résolu avec la solution ci-dessous.

<Button
        android:id="@+id/btnRemove"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/btnEdit"
        android:layout_weight="1"
        android:background="@drawable/btn"
        android:text="@string/remove" 
        android:onClick="btnRemoveClick"
        />

btnRemoveClick Événement de clic

public void btnRemoveClick(View v)
{
    final int position = listviewItem.getPositionForView((View) v.getParent()); 
    listItem.remove(position);
    ItemAdapter.notifyDataSetChanged();

}

9voto

Rafal Points 136

Vous avez probablement trouvé comment le faire, mais vous pouvez appeler

ListView.setItemsCanFocus(true)

et maintenant vos boutons vont attirer l'attention

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