Android:具有多个可点击button的ListView元素

我有一个ListView列表中的每个元素包含一个TextView和两个不同的button。 像这样的东西:

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

有了这个代码,我可以为整个项目创build一个OnItemClickListener

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

但是,我不希望整个项目是可点击的,而只是每个列表元素的两个button。

所以我的问题是,我如何使用以下参数为这两个button实现onClickListener:

  • int button (元素的哪个button被点击)
  • int position (这是button点击发生的列表中的元素)

更新:我find了我在下面的答案中描述的解决scheme。 现在我可以通过触摸屏点击/点击button。 但是,我不能用轨迹球手动select它。 它总是select整个列表项,并从那里直接进入下一个列表项忽略button,即使我为getView()的button设置.setFocusable(true).setFocusable(true) getView()

我也将此代码添加到我的自定义列表适配器:

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

这导致没有任何列表项可以被选中。 但它并没有帮助使嵌套button可选。

任何人的想法?

对此的解决scheme实际上比我想象的要容易。 您可以简单地为您使用的button添加自定义适配器的getView()方法setOnClickListener()。

任何与该button相关的数据必须在getView()添加myButton.setTag() ,并且可以通过view.getTag()view.getTag()访问。

我在博客上发布了一个详细的解决scheme,作为教程。

这是一个附件@ znq的答案…

有很多情况下,你想知道一个点击项目的行位置,你想知道该行中的哪个视图被点击。 这在平板电脑用户界面中将变得更为重要。

您可以使用以下自定义适配器执行此操作:

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

对于未来的读者:

要使用轨迹球手动selectbutton,请使用:

 myListView.setItemsCanFocus(true); 

并禁用整个列表项目的重点:

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

它对我来说工作得很好,我可以点击触摸屏上的button,也可以使用键盘点击鼠标

我没有太多的经验比上面的用户,但我面临同样的问题,我解决了这个问题,下面的解决scheme

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

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

也许你已经find了如何做,但你可以打电话

 ListView.setItemsCanFocus(true) 

现在你的button将抓住焦点

我不知道是最好的方法,但工作正常,所有的代码保持在你的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; } } 

我知道这是晚了,但这可能会有所帮助,这是我如何编写自定义适配器类为不同的点击操作的一个例子

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

这个实现的平台解决scheme不是使用长按显示的上下文菜单吗?

问题作者是否知道上下文菜单? 在一个列表视图堆叠button有性能影响,将凌乱你的用户界面,并违反平台推荐的用户界面devise。

另一方面; 上下文菜单 – 本质上没有被动表示 – 对于最终用户来说并不明显。 考虑logging行为?

本指南应该给你一个好的开始。

http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/