ListView中的OnItemClickListener和OnClickListener

3

我有一个自定义的视图用于自定义ListAdapter中的每一行,我正在尝试执行onClick操作并获取单击来源的列表中的行位置。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:paddingLeft="10dip" android:id="@+id/itemRoot" android:clickable="false">

    <TextView android:layout_width="wrap_content" android:text="TextView"
        android:layout_height="wrap_content" android:id="@+id/itemTxt"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"></TextView>
    <TextView android:layout_toRightOf="@+id/itemTxt" android:text="TextView"
        android:layout_height="wrap_content" android:layout_alignBottom="@+id/itemTxt"
        android:id="@+id/amountTxt" android:paddingLeft="6dip"
        android:layout_centerVertical="true" android:layout_width="match_parent"></TextView>
    <ImageView android:id="@+id/delBtn" android:layout_height="wrap_content"
        android:src="@drawable/delete" android:layout_width="wrap_content"
        android:layout_alignParentRight="true" android:paddingRight="10dip"
        android:layout_centerVertical="true"></ImageView>

</RelativeLayout>

我想知道如何在点击TextView或ImageView时获取它们所在的列表行。我尝试使用OnItemClickListener,可以获取点击来自哪一行。但是,一旦我为视图注册了一个OnClick监听器,onItemClicked()方法就被跳过了,直接执行onClick()方法,但是我不知道如何获取视图所在的行位置(至少我不知道如何获取)。如果将视图的clickable设置为false,则会调用onItemClicked并尝试手动调用给定视图上的performClick()。但是这仅适用于根元素(RelativeLayout),如果点击来自布局内部的TextView,则无法传播点击。我真的无法想出如何同时获取列表中的位置和执行onClick操作。欢迎任何想法。 Alex

在布局中,当将一个视图相对于另一个视图定位时,应该指定锚点的id而不带有 + 符号:android:layout_toRightOf="@id/itemTxt"android:layout_alignBottom="@id/itemTxt"。当为视图创建新的id时(因此在 android:id 属性的值中),使用 "@+id/itemTxt" - rekaszeru
所有的代码都是自动生成的,但我会记住的 :) Alex - Alex
3个回答

6
您可以在ListAdapter的重写getView方法中为每个ImageView和TextView分配适当的OnClickListener。在该方法中,您知道项目的位置,因此可以将其传递给自定义侦听器类,并在那里按照您的意愿使用它:
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
    // TODO: instantiate the layout 
    // here I call a super method
    final View view = super.getView(position, convertView, parent);
    final TextView textView = (TextView)view.findViewById(R.id.itemTxt);
    textView.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Log.i("Click", "TextView clicked on row " + position);
        }
    });
    final ImageView imageView = (ImageView)view.findViewById(R.id.delBtn);
    imageView.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Log.i("Click", "ImageView clicked on row " + position);
        }
    });
    return view;
}

谢谢rekaszeru,这实际上是一个非常巧妙和好的解决方案。 - Alex

5
另一种将OnClickListener置于创建活动中的同一类中的可能选项是向该活动添加 implements OnItemClickListener
public class DisplayListCustom extends Activity implements OnItemClickListener

然后将自定义列表设置为监听

ListView list = (ListView)findViewById(R.id.custom_list);
list.setClickable(true);
list.setOnItemClickListener(this);
list.setAdapter(new CustomListAdapter(getApplicationContext(), listItems));

最后在onItemClick返回中,您可以使用资源ID查找内部视图。
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    LinearLayout listItem = (LinearLayout) v;
    TextView clickedItemView = (TextView) listItem.findViewById(R.id.name);
    String clickedItemString = clickedItemView.getText().toString();
    Log.i("DisplayListCustom", "Click detected " + clickedItemString + ", position " + Integer.toString(position));

这是我采用的解决方案。我使用LinearLayout作为自定义布局容器,但我认为RelativeLayout同样适用。


不错!我更喜欢这种方法,而不是rekaszeru建议的匿名类方法。 - Someone Somewhere

0
你需要扩展你的TextView等,重写点击方法,执行适当的操作,然后关键是返回false,这样它就会传播到ListView。

我想知道是否有一种可以覆盖的方法,返回false并欺骗认为事件未被消耗的技巧。谢谢。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接