web-dev-qa-db-fra.com

Comment déclencher onListItemClick dans Listactivity avec des boutons dans la liste?

J'ai une ListActivity simple qui utilise un ListAdapter personnalisé pour générer les vues dans la liste. Normalement, le ListAdapter remplit simplement les vues avec TextViews, mais maintenant je veux aussi y mettre un bouton.

Cependant, d'après ma compréhension et mon expérience, le fait de placer une vue focalisable dans l'élément de liste empêche le déclenchement de onListItemClick () dans ListActivity lorsque l'utilisateur clique sur l'élément de liste. Le bouton fonctionne toujours normalement dans l'élément de liste, mais lorsque quelque chose en plus du bouton est enfoncé, je veux que onListItemClick soit déclenché.

Comment puis-je faire fonctionner cela?

89
CodeFusionMobile

comme je l'ai écrit dans commentaire précédent la solution consiste à définirFocusable (false) sur ImageButton.

Il existe une solution encore plus élégante, essayez d'ajouter Android:descendantFocusability="blocksDescendants" dans la disposition racine de l'élément de liste. Cela rendra les clics sur ListItem possibles et séparément, vous pouvez gérer les clics sur les boutons ou les boutons ImageButton

J'espère que ça aide ;)

À votre santé

99
Ewoks

J'espère pouvoir vous aider ici. Je suppose que vous avez une disposition personnalisée pour les éléments listView, et cette disposition se compose de boutons et d'autres vues - comme TextView, ImageView ou autre. Vous voulez maintenant déclencher un événement différent lors du clic sur le bouton et un événement différent déclenché sur tout le reste.

Vous pouvez y parvenir sans utiliser onListItemClick () de votre ListActivity.
Voici ce que vous devez faire:

Vous utilisez une disposition personnalisée, vous remplacez donc probablement la méthode getView () de votre adaptateur personnalisé. L'astuce consiste à définir les différents écouteurs pour votre bouton et différents pour l'ensemble de la vue (votre ligne). Jetez un œil à l'exemple:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

Votre classe OnItemClickListener pourrait être déclarée comme ici:

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

Bien sûr, vous ajouterez probablement quelques paramètres supplémentaires au constructeur OnItemClickListener.
Et une chose importante - l'implémentation de getView montrée ci-dessus est assez moche, normalement vous devriez utiliser le modèle ViewHolder pour éviter les appels findViewById .. mais vous le savez probablement déjà.
Mon fichier custom_row.xml est RelativeLayout avec Button of id "button", TextView of id "text" et ImageView of id "image" - juste pour que les choses soient claires.
Cordialement!

59
Ramps

Lorsqu'un ListView personnalisé contient des éléments focalisables, onListItemClick ne fonctionne pas (je pense que c'est le comportement attendu). Supprimez simplement le focus de la vue personnalisée, cela fera l'affaire:

Par exemple:

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         …
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
        …       
    }
}
18
Rabi

J'ai le même problème: OnListItemClick n'est pas viré! [RESOLU]
Cela se produit sur une classe qui étend ListActivity,
avec une disposition pour ListActivity qui contient TextBox et ListView imbriqués dans LinearLayout
et une autre disposition pour les lignes (une CheckBox et une TextBox imbriquées dans LineraLayout).

C'est du code:

res/layout/configpage.xml (principal pour ListActivity)

<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"  
    Android:orientation="vertical"  
    Android:layout_width="fill_parent"  
    Android:layout_height="fill_parent" > 
    <TextView  
        Android:id="@+id/selection"  
        Android:layout_width="fill_parent"  
        Android:layout_height="wrap_content"  
        Android:text="pippo" /> 
    <ListView  
        Android:id="@Android:id/list"  
        Android:layout_width="fill_parent"  
        Android:layout_height="wrap_content"  
        Android:drawSelectorOnTop="false"  
        Android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:Android="http://schemas.Android.com/apk/res/Android"  
  Android:layout_width="fill_parent"  
  Android:layout_height="wrap_content"> 
  <CheckBox  
      Android:id="@+id/img"  
      Android:layout_width="wrap_content"  
      Android:layout_height="wrap_content"  
      **Android:focusable="false"**  
      **Android:focusableInTouchMode="false"** /> 

  <TextView  
      Android:id="@+id/testo"  
      Android:layout_width="wrap_content"  
      Android:layout_height="wrap_content"  
      **Android:focusable="false"**  
      **Android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ConfigPage.Java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

Cela commence à fonctionner lorsque j'ai ajouté sur row.xml

  • Android:focusable="false"
  • Android:focusableInTouchMode="false"

J'utilise Eclipse 3.5.2
SDK Android 10.0.1
min SDK version: 3

J'espère que ceci est utile
... et désolé pour mon anglais :(

13
rfellons

ajoutez simplement Android:focusable="false" comme l'un des attributs de votre bouton

2
John
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});
1
confucius

J'ai eu le même problème avec ToggleButton. Après une demi-journée à me cogner la tête contre un mur, je l'ai finalement résolu. C'est aussi simple que de rendre la vue focalisable non focalisable, en utilisant 'Android: focalisable'. Vous devez également éviter de jouer avec la focalisation et la cliquabilité (je viens de créer des mots) de la ligne de liste, laissez-les simplement avec la valeur par défaut.

Bien sûr, maintenant que vos vues focalisables dans la ligne de liste ne sont pas focalisables, les utilisateurs utilisant le clavier peuvent avoir des problèmes, eh bien, les focaliser. Ce n'est probablement pas un problème, mais juste au cas où vous voudriez écrire des applications 100% parfaites, vous pourriez utiliser l'événement onItemSelected pour rendre les éléments de la ligne sélectionnée focalisables et les éléments de la ligne précédemment sélectionnée non focalisables.

1
Ridiculous