【问题标题】:Facing critical issue: Toggle image source inside Listview using ViewHolder Pattern面临的关键问题:使用 ViewHolder 模式切换 Listview 内的图像源
【发布时间】:2014-03-02 06:58:25
【问题描述】:

在我的 Listview 的 ListItem 中,我有多个控件,其中一个是 imageview。我的目的是用户单击该图像时,源应更改为其他内容。我正在实现 ViewHolder 模式,现在我可以在点击时切换源。我当前的问题是,当我向下滚动时,正在创建新视图(重新使用),并且当我尝试再次向上移动时,我切换图像的列表项再次使用默认图像源创建,因为我的数据源列表保持不变.请帮忙。

        private class ViewHolder : Java.Lang.Object
    {
        //Activity context;
        public MyTextView HadithBook;
        public MyTextView HadithChapter;
        public MyTextView HadithText;
        public ImageView FavButton;
        public ImageView ShareButton;
        public EventHandler Handler;
        public MyTextView RowId;
        public MyTextView IsFavorite;
    }


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


        ViewHolder holder = null;
        if (convertView == null) 
        {
            convertView = context.LayoutInflater.Inflate (Resource.Layout.HadithListViewItem, null);
            holder = new ViewHolder ();
            holder.HadithBook = convertView.FindViewById<MyTextView> (Resource.Id.HadithBook);
            holder.HadithChapter = convertView.FindViewById<MyTextView> (Resource.Id.HadithChapter);
            holder.HadithText = convertView.FindViewById<MyTextView> (Resource.Id.HadithText);
            holder.FavButton = convertView.FindViewById<ImageView> (Resource.Id.favButton);
            holder.ShareButton = convertView.FindViewById<ImageView> (Resource.Id.ShareButton);
            holder.IsFavorite = convertView.FindViewById<MyTextView> (Resource.Id.IsFavorite);
            holder.RowId = convertView.FindViewById<MyTextView> (Resource.Id.RowId);

            holder.Handler = (s, e) => FavoriteHandler (s, e, holder);

            convertView.Tag = holder;
        }

        if (holder == null) 
        {
            holder = (ViewHolder)convertView.Tag;

            holder.FavButton.Click -= holder.Handler;
        }

        var item = items[position];

        holder.HadithBook.Text = item.BookName;
        holder.HadithChapter.Text = item.ChapterName + " - " + item.HadithID;

        if (!string.IsNullOrEmpty (keyword) & !string.IsNullOrWhiteSpace (keyword)) {
            holder.HadithText.TextFormatted = (Html.FromHtml (ReplaceEx ((item.HadithText).ToString (), keyword, "<font color='#ff9000'><b>" + keyword + "</b></font>")));
        } else {
            holder.HadithText.TextFormatted =Html.FromHtml(item.HadithText);
        }






        if (holder.FavButton.Tag.Equals(0)) 
        {
            holder.FavButton.Tag = 0;
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_not_important);

        } else 
        {
            holder.FavButton.Tag = 1;
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_important);
        }

        holder.FavButton.Click += holder.Handler;
        convertView.SetOnClickListener (null);

        return convertView;
        }


        void FavoriteHandler (object sender, EventArgs e, ViewHolder holder)
    {
        Database db = new Database ();
        if (holder.FavButton.Tag.Equals (0)) {
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_important);
            holder.FavButton.Tag = 1;
            db.InsertQuery ("insert into favorite values ('" + holder.RowId + "');");

        } else if (holder.FavButton.Tag.Equals (1)) {
            holder.FavButton.SetImageResource (Resource.Drawable.ic_action_not_important);
            holder.FavButton.Tag = 0;
            db.InsertQuery ("Delete from favorite where id ='" + holder.RowId + "';");
        }
        db = null;

    }

【问题讨论】:

  • 这是 monodroid 应用程序。我的意思是使用 C# 的 Android 应用程序。先生,这编译得很好,编译错误为零。
  • 好的,好的,我会删除我的评论。

标签: android listview xamarin.android xamarin android-imageview


【解决方案1】:

这是几乎每个人在学习如何实现适配器时都会陷入的陷阱。

问题是您将数据存储在该位置唯一的视图中。例如,您在使用值设置之前从 holder.FavButton.Tag 读取,因此您当前的代码期望该标签为您保留数据。

当您滚动浏览列表视图时,视图会被回收,因此您正在从另一个位置读取数据。您不能在视图持有者中缓存位置相关数据。相反,它用于保存所有位置共有的布局元素(即视图是可覆盖的,因此在 getView 方法中名称为“convertView”)。您必须通过其他方式缓存该数据,例如按位置缓存数据的哈希图。

【讨论】:

  • 你的意思是我应该维护一个字典项或哈希表来存储数据,如..字典()
  • 然后在我的点击事件中,我应该相应地更新这个字典项,并且在我的 getview 方法中,我应该检查字典项中该位置的相应值。这是要走了吗????
  • 酷.. 非常感谢...还有一个问题,我应该为所有 ListItems 或仅为用户单击切换图像的那些 ListItems 维护 Dictionary 项目,因为我的 listview 有大约 3000 个 listitems。
  • 如果您希望只有一小部分被点击,那么只将收藏夹放在列表中,并且使 null 表示不收藏。即使您提交所有 3000 个布尔值,也没什么大不了的。如果这些来自本地数据库,android 可以非常快速地读取一个简单的数据库(闪存),并且可以在 getView 方法中动态填充列表视图(如果需要,也可以通过自定义异步方法)。
  • 实际上我在 android 上有 sqlite 数据库,我用该数据库中的数据填充我的列表视图,首先将所有数据读入 List,然后使用我的适配器将这些数据加载到列表视图中。如果用户更改收藏夹,我必须将其写回数据库。什么是最好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
相关资源
最近更新 更多