Xamarin.Android:RecyclerView.Adapter,错误的元素回收

时间:2017-07-20 16:55:10

标签: android android-recyclerview xamarin.android

我有这个选择活动我用来选择元素。它基于超类,它使用 RecyclerView 。它是使用泛型构建的,因此很容易使“选择器”传递模型类。可以使用它来进行单个或多个选择。

问题是,如果我选择元素并滚动,有时我也会看到其他行被选中。 行为很奇怪,如果我向下滚动一切看起来没问题,如果我返回到足以再次看到所选行并且我重新开始向下滚动,我看到其他行重复。它只是一个图形化的东西,所以如果我按下ok,活动只返回正确的元素。

我很确定这是回收的问题,所以我尝试将 IsRecyclable 设置为不可回收所选行,但它不起作用。

有什么建议吗?

enter image description here

部分 RecyclerView.Adapter

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup viewGroup, int position)
{
    var itemView = LayoutInflater.From(viewGroup.Context).Inflate(Resource.Layout.activity_basemodel_item, viewGroup, false);
    var viewHolder = new BaseModelViewHolder(itemView, OnClick, OnLongClick, DetailActivityType);
    viewHolder.IsRecyclable = !SelectionEnabled;

    return viewHolder;
}

public void HighLight(RecyclerView.ViewHolder viewHolder, int position)
{
    if (!SelectionEnabled) { return; }

    var guid = ((BaseModelViewHolder)viewHolder).Model.Id;
    if (SelectedGuids.Contains(guid))
    {
        viewHolder.ItemView.Selected = true;
        viewHolder.ItemView.SetBackgroundColor(SelectedItemBackgroundColor);
    }
    else
    {
        viewHolder.ItemView.Selected = false;
    }
}

public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
    TModel model = DataSet[position];

    String title = model.Title;
    String subtitle = model.Subtitle;

    ((BaseModelViewHolder)viewHolder).TxtTitle.SetText(title, TextView.BufferType.Normal);
    if (!String.IsNullOrEmpty(subtitle) && !subtitle.Equals(title))
    {
        ((BaseModelViewHolder)viewHolder).TxtSubtitle.SetText(subtitle, TextView.BufferType.Normal);
    }
    ((BaseModelViewHolder)viewHolder).Model = model;

    this.HighLight(viewHolder, position);
}

1 个答案:

答案 0 :(得分:1)

在ViewModel中传递Model时,RecyclerViews会显示奇怪的行为:

((BaseModelViewHolder)viewHolder).Model = model; //problem

要解决此问题,您可以这样做:

public void HighLight(RecyclerView.ViewHolder viewHolder, int position)
{
    if (!SelectionEnabled) { return; }

    TModel model = DataSet[position];
    var guid = model.Id;
    if (SelectedGuids.Contains(guid))
    {
        viewHolder.ItemView.SetBackgroundColor(SelectedItemBackgroundColor);
    }
    else
    {
        viewHolder.ItemView.SetBackgroundColor(DefaultItemBackgroundColor);
    }
}

public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
    TModel model = DataSet[position];

    String title = model.Title;
    String subtitle = model.Subtitle;

    ((BaseModelViewHolder)viewHolder).TxtTitle.SetText(title, TextView.BufferType.Normal);
    if (!String.IsNullOrEmpty(subtitle) && !subtitle.Equals(title))
    {
        ((BaseModelViewHolder)viewHolder).TxtSubtitle.SetText(subtitle, TextView.BufferType.Normal);
    }

    this.HighLight(viewHolder, position);

    // To highlight an item when clicked:
    viewHolder.ItemView.Click -= HighLight_Item;
    viewHolder.ItemView.Click += HighLight_Item; //This is to avoid subscribing the event everytime the view is shown
}

选择项目:

private void HighLight_Item(object sender, EventArgs e)
{
    //You need to pass the RecyclerView as an argument to the Adapter
    int position = this.recyclerView.GetChildAdapterPosition((View)sender);
    TModel model = DataSet[position];
    var guid = model.Id;
    //If already contains then remove, if doesn't contain then add
    if(SelectedGuids.Contains(guid)) SelectedGuids.Remove(guid);
    else SelectedGuids.Add(guid);
    //This will update the item view
    this.NotifyItemChanged(position); 
}