【问题标题】:RecyclerView OnClick changing items at other positionRecyclerView OnClick 在其他位置更改项目
【发布时间】:2018-07-09 14:10:59
【问题描述】:

我在 RecyclerView 中有一个字符串列表。我需要能够单击列表中的项目并将背景更改为黄色。我可以单击一个项目并更改背景,但是当我向下滚动列表时,我看到列表中的另一个项目的背景也变成了黄色?

我尝试了许多不同的方法来实现这一点。我尝试设置一个界面,点击 ViewHolder 等。

我的代码如下。

活动:

[Activity(Label = "PregnancyListActivity")]
public class PregnancyListActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PregnantAnimalAdapter mAdapter;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.PregnancyListLayout);

        mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);

        // Plug in the linear layout manager:
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.SetLayoutManager(mLayoutManager);

        // Plug in my adapter:
        mAdapter = new PregnantAnimalAdapter();
        mAdapter.ItemClick += MAdapter_ItemClick;
        mRecyclerView.SetAdapter(mAdapter);
    }
}

查看持有人

[Activity(Label = "PregnantAnimalViewHolder")]
public class PregnantAnimalViewHolder : RecyclerView.ViewHolder
{
    public LinearLayout mBackground { get; private set; }
    public TextView mAnimalTag { get; private set; }

    public PregnantAnimalViewHolder(View itemView) : base(itemView)
    {
        // Locate and cache view references:
        mBackground = itemView.FindViewById<LinearLayout>(Resource.Id.pregnancyBackground);
        mAnimalTag = itemView.FindViewById<TextView>(Resource.Id.animalTag);

    }
}

适配器:

public class PregnantAnimalAdapter : RecyclerView.Adapter
{
public PregnantAnimalAdapter pregnantAnimalAdapter;
public List<PregAnimals> mAnimals;

public PregnantAnimalAdapter()
{
    mAnimals = new List<PregAnimals>{
        new PregAnimals("111", false),
        new PregAnimals("112", false),
        new PregAnimals("113", false),
        new PregAnimals("114", false),
        new PregAnimals("115", false),
        new PregAnimals("221", false),
        new PregAnimals("222", false),
        new PregAnimals("223", false),
        new PregAnimals("224", false),
        new PregAnimals("225", false),
        new PregAnimals("331", false),
        new PregAnimals("332", false),
        new PregAnimals("333", false),

        new PregAnimals("444", false),
        new PregAnimals("443", false),
        new PregAnimals("554", false),
        new PregAnimals("4435", false),
        new PregAnimals("4234", false),
        new PregAnimals("543", false),
        new PregAnimals("3452", false),
        new PregAnimals("3321", false),
        new PregAnimals("6676", false),
        new PregAnimals("4367", false)
    };
}

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
    View itemView = LayoutInflater.From(parent.Context).
                                  Inflate(global::RecordMilk.Resource.Layout.PregnancyItem, parent, false);

    PregnantAnimalViewHolder vh = new PregnantAnimalViewHolder(itemView);

    vh.mBackground.Click += (object sender, EventArgs e) => {
        mAnimals[vh.LayoutPosition].Preg = true;
    };

    return vh;
}



public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    PregnantAnimalViewHolder vh = holder as PregnantAnimalViewHolder;

    vh.mAnimalTag.Text = mAnimals[position].Tag;
    if (mAnimals[position].Preg == true)
    {
        vh.mBackground.SetBackgroundResource(RecordMilk.Resource.Color.munster_yellow);
    }

}



public override int ItemCount
{
    get { return mAnimals.Count; }
}
}

public class PregAnimals
{
    public string Tag { get; set; }
    public bool Preg { get; set; }

    public PregAnimals(string tag, bool preg)
    {
        Tag = tag;
        Preg = preg;
    }

}

我很困惑为什么它不只是在列表中设置项目。任何帮助将不胜感激。

提前致谢!

【问题讨论】:

  • 您需要更好地阅读 RecyclerView 文档 :) 您通常不会直接对回收器视图进行操作,而是将位置存储在单击时,然后调用 notifyItemChanged 并在 onBindViewHolder 中应用选择。您可能还需要取消选择之前选择的条目。
  • “您需要更好地阅读 RecyclerView 文档 :)” - 哈哈,谢谢。我一直在阅读如此多的示例和 Xamarin 站点,但是在运行它时尝试阅读和理解之后,头脑很困惑。 “您可能还需要取消选择先前选择的条目”-是的,这是我最终能够使第 1 步正常工作之后的第 2 步:(。
  • 直接使用 RecyclerView 的子视图通常是个坏主意,因为 RV 会回收它们。当孩子滚动出屏幕时,它会被缓存,并且可以随时重新引入,作为完全不同条目的出口视图。如果您在 onBindViewHolder 中不考虑这一点,您最终会得到不一致的视图状态。支持库 28.0.0 添加了选择处理,但我还没有使用它们,所以我无法评论。您可能想查看它们。
  • @sigsegv - 这真的很有帮助。谢谢!最好把它做好,所以如果需要一点学习,那就是它所需要的。谢谢大佬

标签: android xamarin xamarin.android android-recyclerview


【解决方案1】:

尝试在适配器中添加这一行:

@Override
public int getItemViewType(int position) {
    return position; 
}

【讨论】:

  • 非常感谢!这对我有用:)
【解决方案2】:

问题是 RecyclerView 正在做它应该做的 - 回收视图。您更改了颜色的 View 正在被重新用于新项目,但其颜色仍处于选中状态。

假设您希望选择保留,您需要跟踪选择了哪一个,并在 OnBindViewHolder 中将背景颜色设置为选中或未选中的颜色。否则只需将背景设置为未选中即可。

此外,您可以创建一个 StateListDrawable 并将其分配给具有选中/未选中状态的背景,因此您只需将视图的状态设置为选中即可。优点是它将所有样式保存在资源中。

public class PregnantAnimalViewHolder : RecyclerView.ViewHolder
{
    public LinearLayout mBackground { get; private set; }
    public TextView mAnimalTag { get; private set; }
    public bool Selected {get;set;}
    public int position {get;set;}

    public PregnantAnimalViewHolder(View itemView) : base(itemView)
    {
        // Locate and cache view references:
        mBackground = itemView.FindViewById<LinearLayout>(Resource.Id.pregnancyBackground);
        mAnimalTag = itemView.FindViewById<TextView>(Resource.Id.animalTag);

    }
}

然后在 OnBindViewHolder 中

public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
    PregnantAnimalViewHolder vh = holder as PregnantAnimalViewHolder;

    vh.mAnimalTag.Text = mAnimals[position];
    vh.position = position;
    vh.View.SetBackgroundResource(
         vh.Selected?Resource.Color.munster_yellow:Resource.Color.whatever);

    // or vh.View.SetSelected(vh.Selected) for using StateListDrawable as the background

}

【讨论】:

  • 另外,PregnantAnimalViewHolder 不是 Activity 属性,因为它不是 Activity :)
  • 完全忘记了 Activity 属性在那里 xD。接得好!您的解决方案现在完全有意义(facepalm)。我非常专注于试图解决为什么它不起作用,我不只是坐下来认为这是“回收”视图。会按照你说的去尝试,希望会带来好消息:)
  • 很高兴我能帮上忙。我把所有这些都写在脑海里,所以可能有一两个语法错误。
  • 我认为对“已选择”属性的说明确实使问题变得模糊!一两个语法错误是可以接受的;P
  • 我会尝试添加您推荐的内容:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多