【问题标题】:ListView ItemClick event not firing for custom ListView adapterListView ItemClick 事件未针对自定义 ListView 适配器触发
【发布时间】:2019-06-10 20:17:54
【问题描述】:

因此,当我单击自定义 ListView 中的项目时,我的 Main Activity 中的 ItemClick 事件没有触发。我查看了其他答案,并认为这两个 Image 按钮会将焦点移开,所以我尝试了不同的方法将两个按钮的可聚焦性设置为 false,甚至在 ImageView 上尝试过,但到目前为止它不起作用.有人能告诉我为什么吗?这是我的代码。

每个项目的标记。

Layout1.axml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#FFDAFF7F"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:id="@+id/SpiceRowItem">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >
        <ImageView
            android:id="@+id/Thumbnail"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:background="#000000"
         />
        <LinearLayout
            android:id="@+id/Text"
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dip">
            <TextView
                android:text="Allspice"
                android:id="@+id/Heading"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FF7F3300"
                android:textSize="20dip"
                android:textStyle="italic"
         />
            <TextView
                android:text="Warm, sweet"
                android:id="@+id/Flavour"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="14dip"
                android:textColor="#FF267F00"
         />
        </LinearLayout>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/ImageWrap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_alignParentRight="true">
        <ImageButton
            android:text="Cupboard"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:id="@+id/AddToCupboard" />
        <ImageButton
            android:text="List"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:id="@+id/AddToList" />
    </LinearLayout>


</RelativeLayout>

还有来自我的自定义适配器的 GetView 方法(我正在使用委托,所以我可以封装变量“位置”):

SpiceListAdapter.cs

public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View row = convertView;

            if (row == null)
            {
                row = LayoutInflater.From(mContext).Inflate(Resource.Layout.layout1, null, false);
            }

            ImageView Thumbnail = row.FindViewById<ImageView>(Resource.Id.Thumbnail);
            TextView Heading = row.FindViewById<TextView>(Resource.Id.Heading);
            TextView Flavour = row.FindViewById<TextView>(Resource.Id.Flavour);
            ImageButton AddToCupboard = row.FindViewById<ImageButton>(Resource.Id.AddToCupboard);
            ImageButton AddToList = row.FindViewById<ImageButton>(Resource.Id.AddToList);
            RelativeLayout SpiceRowItem = row.FindViewById<RelativeLayout>(Resource.Id.SpiceRowItem);

            //Populates heading and flavour of each row

            Heading.Text = mItems[position].name.ToString();
            Flavour.Text = mItems[position].flavour.ToString();

            //Populate button pictures

            if (mItems[position].cupboard)
            {
                AddToCupboard.SetImageResource(Resource.Drawable.CupboardClosed);
            }
            else
            {
                AddToCupboard.SetImageResource(Resource.Drawable.CupboardOpen);
            }
            if (!mItems[position].list)
            {
                AddToList.SetImageResource(Resource.Drawable.ListEmpty);
            }
            else
            {
                AddToList.SetImageResource(Resource.Drawable.ListFull);
            }

            //Adds Thumbnail picture

            var id = (int)typeof(Resource.Drawable).GetField(mItems[position].picture.ToString()).GetValue(null);
            Thumbnail.SetImageResource(id);

            //Adds onclick event for "Add to cupboard"

            AddToCupboard.Click += delegate
            {
                string RemMessage = "Removed From Cupboard";
                string AddMessage = "Added To Cupboard";
                mItems[position].cupboard = !mItems[position].cupboard;
                if (!mItems[position].cupboard)
                {
                    AddToCupboard.SetImageResource(Resource.Drawable.CupboardOpen);
                    Toast.MakeText(mContext, RemMessage, ToastLength.Short).Show();
                }
                else
                {
                    AddToCupboard.SetImageResource(Resource.Drawable.CupboardClosed);
                    Toast.MakeText(mContext, AddMessage, ToastLength.Short).Show();
                }

            };

            //Adds onclick event for "Add to shopping list"


            AddToList.Click += delegate
            {
                string RemMessage = "Removed From Shopping List";
                string AddMessage = "Added To Shopping List";
                mItems[position].list = !mItems[position].list;
                if (!mItems[position].list)
                {
                    AddToList.SetImageResource(Resource.Drawable.ListEmpty);
                    Toast.MakeText(mContext, RemMessage, ToastLength.Short).Show();
                }
                else
                {
                    AddToList.SetImageResource(Resource.Drawable.ListFull);
                    Toast.MakeText(mContext, AddMessage, ToastLength.Short).Show();
                }
            };
                return row;
          }

最后在 Main Activity 中实现:

MainActivity.cs

//Instantiate Adapters
            SpiceListAdapter _adapter = new SpiceListAdapter(this, spices);
            SpiceListAdapter _CupboardAdapter = new SpiceListAdapter(this, cupboard);
            SpiceListAdapter _ShoppingAdapter = new SpiceListAdapter(this, shoppingList);
            _lv.Adapter = _adapter;

//Click Event handlers
            _lv.ItemClick += _lv_ItemClick;

private void _lv_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            Console.WriteLine("Poop");
        }

附言出于某种原因,我在测试时使用了愚蠢的控制台字符串,它只是让我保持理智:D。

【问题讨论】:

    标签: c# android listview xamarin.android android-listadapter


    【解决方案1】:

    您可以尝试在这样的代码中设置属性:

    //对于 AddToCupboard

    AddToCupboard.Focusable = false;
    AddToCupboard.FocusableInTouchMode = false;
    AddToCupboard.Clickable = true;
    AddToCupboard.Click += delegate
            {
               //....
            };
    

    // 用于添加列表

    AddToList.Focusable = false;
    AddToList.FocusableInTouchMode = false;
    AddToList.Clickable = true;
    AddToList.Click += delegate
            {
               //....
            };
    

    另一种方法: 最简单的方法是将其根 ViewGroup 设置为android:descendantFocusability="blocksDescendants",因此它将阻止对其进行聚焦的每个控件。

    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#FFDAFF7F"
    android:paddingLeft="5dp"
    android:paddingRight="5dp"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:descendantFocusability="blocksDescendants"
    android:id="@+id/SpiceRowItem">
    

    【讨论】:

    • 我已经尝试了所有方法,但从未成功:-|但我确实找到了解决方法。我很快就会发布代码。
    【解决方案2】:

    本身不是一个答案,但它是一种解决我的问题的解决方法,可能对其他人有用。

    所以我创建了一个包含单个 int 变量的类并在 MainActivity 中实例化它(可以只声明一个 int 但我想有一个类来保存数据,因为对象通过引用传递)

     class PosHolder
        {
            public int pos { get; set; }
        }
    

    在 MainActivity 中

    PosHolder _pos = new PosHolder();
    
    

    我将我选择的函数作为 lambda 表达式和 _pos 都传递给了我的适配器构造函数

    SpiceListAdapter _adapter = new SpiceListAdapter(this, spices, () => { MyFunction(); }, _pos);
    

    在我的适配器类中,我创建了一个动作,向我的根 axml 布局节点添加了一个单击侦听器。此单击事件将 _pos 的值更改为“位置”,然后使用 click.Invoke() 方法调用传递给构造函数的函数。

    //create action
    public Action Click { get; set; }
    // Adapter Constructor
    public SpiceListAdapter(Context context, List<Spice> names, Action click, PosHolder Pos)
            {
                mItems = names;
                mContext = context;
                Click = click;
                mPos = Pos;
                mCupboard = cupboard;
                mShopList = shoppingList;
            }
    //Click event
    SpiceRowItem.Click += delegate
                {
                    mPos.pos = position;
                    Click?.Invoke();
                };
    

    我可能与最佳实践相去甚远,但它对我有用并解决了我的问题。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      相关资源
      最近更新 更多