面临关键问题:使用ViewHolder Pattern在Listview中切换图像源

时间:2014-03-02 06:58:25

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

在我的Listview的ListItem中,我有一个多个控件,其中一个是imageview。我的目的是当用户点击该图片时,来源应该更改为其他内容。我正在实现ViewHolder Pattern,现在我可以在点击时切换源。我当前的问题是,当我向下滚动新视图被创建(重新使用),当我再次向上移动时,我切换图像的listitem再次使用默认图像源创建,因为我的数据源LIST保持不变。请帮助。

        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;

    }

1 个答案:

答案 0 :(得分:0)

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

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

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