c# - Monodroid - 处理重用 ListView 行的 subview 上的事件

标签 c# android mono xamarin xamarin.android

Android 的 ListView 重新使用已滚出 View 的行。 但是,在 C# 中处理行的 subview 上的事件时,这似乎是一个问题。

在 Java 中添加事件处理程序的公认方法是显式设置处理程序,如下所示:

ImageView img = (ImageView) row.findViewById(R.id.pic);
img.setOnClickListener(new View.OnClickListener() {  
    public void onClick(View v) {
        System.out.println(position);
    }  
});

Xamarin 网站上的文档鼓励开发人员使用 C# 的 add 事件监听器模式,该模式不适用于重复使用的行:

ImageView img = row.FindViewById<ImageView> (Resource.Id.pic);
img.Click += (sender, e) => {
    Console.WriteLine(position);
};

上面设置事件处理程序的 Java 模式非常适合行重用,而下面添加事件处理程序的 C# 模式导致处理程序堆积在子进程上重用行的 View 。

下面的代码显示了我编写的自定义 BaseAdapter 中的 GetView 方法。

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

    //TODO: solve event listener bug. (reused rows retain events).
    if (row == null) {
        row = LayoutInflater.From (userListContext)
                .Inflate (Resource.Layout.UserListUser, null, false);
    }

    ImageView profilePic = row.FindViewById<ImageView> (Resource.Id.profilePic);

    //if(profilePic.Clickable) { /** kill click handlers? **/ }
    profilePic.Click += async (object sender, EventArgs e) => {
        Bundle extras = new Bundle();
        extras.PutString("id", UserList[position].id);

        Intent intent = new Intent(userListContext, typeof(ProfileActivity));
        intent.PutExtras(extras);
        postListContext.StartActivity(intent);
    };

    return row;
}

问题是,当一行被重复使用时,profilePic View 仍然附加了原始的“点击”处理程序。

有没有办法 (a) 消除 profilePic.Click 或 (b) 使用 Android 的 profilePic.SetOnClickListener 具有匿名函数的 Java 模式?

或者,是否有更好的模式可以让“点击”处理程序仍然可以访问 position 的正确值?

最佳答案

Or, is there a better pattern to use where the "click" handler can still access the proper value of position?

使用 setTag/getTag 方法在 ImageView 点击监听器的 Click 方法中获取被点击行的正确位置:

profilePic.SetTag(Resource.Id.profilePic, position);
profilePic.Click += async (object sender, EventArgs e) => {
        int clickedPos = (int)(((Button)sender).GetTag (Resource.Id.profilePic));
        Bundle extras = new Bundle();
        extras.PutString("id", UserList[clickedPos].id);
        ......
};

关于c# - Monodroid - 处理重用 ListView 行的 subview 上的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28534257/

相关文章:

c# - FreeImage.LoadFromStream 对 CR2 文件失败

android - 无法将 'Column' 内联方法调用到 Jetpack compose 中的本地最终乐趣 <anonymous>()

android - Kotlin 单例应用程序类

c# - 对象数组,在一个线程中更新并在另一个线程中读取

c# - 无需互操作即可获取 PDF 中的所有单词及其位置

c# - 验证长类型输入

c# - VS2010 中的 2.0 框架 .net 引用缺少 System.web.extensions 引用 dll?

c# - 从 Mysql 数据库填充 DataGrid

android - 卸载应用程序后如何删​​除备份应用程序?

macos - 在 MAC OS X 上的 MONO 中调用命令行