J'ai un ListView
où chaque élément de la liste contient un TextView et deux boutons différents. Quelque chose comme ça:
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'élément entier:
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'élément entier soit cliquable, mais uniquement les deux boutons de chaque élément de liste.
Ma question est donc de savoir comment implémenter un onClickListener pour ces deux boutons avec les paramètres suivants:
int button
(sur quel bouton de l'élément a été cliqué)int position
(qui est l'élément de la liste sur lequel le clic sur le bouton s'est produit)
Mise à jour: j'ai trouvé une solution comme décrit dans ma réponse ci-dessous. Maintenant, je peux cliquer / appuyer sur le bouton via l'écran tactile. Cependant, je ne peux pas le sélectionner manuellement avec le trackball. Il sélectionne toujours l'élément de liste entier et à partir de là, il passe directement à l'élément de liste suivant en ignorant les boutons, même si j'ai défini .setFocusable(true)
et 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 liste ne peut plus être sélectionné. Mais cela n'a pas aidé à rendre les boutons imbriqués sélectionnables.
Quelqu'un a une idée?
Réponses:
La solution à cela est en fait plus facile que je ne le pensais. Vous pouvez simplement ajouter dans la
getView()
méthode de votre adaptateur personnalisé un setOnClickListener () pour les boutons que vous utilisez.Toutes les données associées au bouton doivent être ajoutées
myButton.setTag()
dans legetView()
et sont accessibles dans onClickListener viaview.getTag()
J'ai posté une solution détaillée sur mon blog sous forme de tutoriel.
la source
C'est en quelque sorte la réponse d'un appendice @ znq ...
Il existe de nombreux cas où vous souhaitez connaître la position de la ligne pour un élément cliqué ET vous souhaitez savoir quelle vue de la ligne a été sélectionnée. Cela sera beaucoup plus important dans les interfaces utilisateur des 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); } }; }
la source
Pour les futurs lecteurs:
Pour sélectionner manuellement les boutons avec le trackball, 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);
Cela fonctionne bien pour moi, je peux cliquer sur les boutons avec écran tactile et permet également de concentrer un clic à l'aide du clavier
la source
Je n'ai pas beaucoup d'expérience que les utilisateurs ci-dessus, mais j'ai rencontré le même problème et j'ai résolu cela 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 Click événement
public void btnRemoveClick(View v) { final int position = listviewItem.getPositionForView((View) v.getParent()); listItem.remove(position); ItemAdapter.notifyDataSetChanged(); }
la source
Vous avez probablement trouvé comment le faire, mais vous pouvez appeler
ListView.setItemsCanFocus(true)
et maintenant vos boutons attireront l'attention
la source
Je ne suis pas sûr d'être le meilleur moyen, mais fonctionne correctement et tout le code reste dans votre ArrayAdapter.
package br.com.fontolan.pessoas.arrayadapter; import java.util.List; import android.content.Context; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageView; import br.com.fontolan.pessoas.R; import br.com.fontolan.pessoas.model.Telefone; public class TelefoneArrayAdapter extends ArrayAdapter<Telefone> { private TelefoneArrayAdapter telefoneArrayAdapter = null; private Context context; private EditText tipoEditText = null; private EditText telefoneEditText = null; private ImageView deleteImageView = null; public TelefoneArrayAdapter(Context context, List<Telefone> values) { super(context, R.layout.telefone_form, values); this.telefoneArrayAdapter = this; this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.telefone_form, parent, false); tipoEditText = (EditText) view.findViewById(R.id.telefone_form_tipo); telefoneEditText = (EditText) view.findViewById(R.id.telefone_form_telefone); deleteImageView = (ImageView) view.findViewById(R.id.telefone_form_delete_image); final int i = position; final Telefone telefone = this.getItem(position); tipoEditText.setText(telefone.getTipo()); telefoneEditText.setText(telefone.getTelefone()); TextWatcher tipoTextWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { telefoneArrayAdapter.getItem(i).setTipo(s.toString()); telefoneArrayAdapter.getItem(i).setIsDirty(true); } }; TextWatcher telefoneTextWatcher = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { telefoneArrayAdapter.getItem(i).setTelefone(s.toString()); telefoneArrayAdapter.getItem(i).setIsDirty(true); } }; tipoEditText.addTextChangedListener(tipoTextWatcher); telefoneEditText.addTextChangedListener(telefoneTextWatcher); deleteImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { telefoneArrayAdapter.remove(telefone); } }); return view; } }
la source
Je sais qu'il est tard mais cela peut aider, voici un exemple comment j'écris une classe d'adaptateur personnalisée pour différentes actions de clic
public class CustomAdapter extends BaseAdapter { TextView title; Button button1,button2; public long getItemId(int position) { return position; } public int getCount() { return mAlBasicItemsnav.size(); // size of your list array } public Object getItem(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.listnavsub_layout, null, false); // use sublayout which you want to inflate in your each list item } title = (TextView) convertView.findViewById(R.id.textViewnav); // see you have to find id by using convertView.findViewById title.setText(mAlBasicItemsnav.get(position)); button1=(Button) convertView.findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //your click action // if you have different click action at different positions then if(position==0) { //click action of 1st list item on button click } if(position==1) { //click action of 2st list item on button click } }); // similarly for button 2 button2=(Button) convertView.findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //your click action }); return convertView; } }
la source
La solution de plate-forme pour cette implémentation n'est-elle pas d'utiliser un menu contextuel qui s'affiche sur un appui long?
L'auteur de la question connaît-il les menus contextuels? L'empilement de boutons dans une liste a des implications sur les performances, encombrera votre interface utilisateur et enfreindra la conception d'interface utilisateur recommandée pour la plate-forme.
Sur le revers; les menus contextuels - par nature de ne pas avoir de représentation passive - ne sont pas évidents pour l'utilisateur final. Pensez à documenter le comportement?
Ce guide devrait vous donner un bon départ.
http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/
la source