Xamarin,ListView和RecyclerView,单击一个项目,选择另一个项目
我在Xamarin,ListView和RecyclerView,单击一个项目,选择另一个项目,xamarin,android-recyclerview,onitemclick,Xamarin,Android Recyclerview,Onitemclick,我在列表视图和回收视图 最初,我创建了一个列表视图,一切正常。然后我为它设置了onClick事件,这样每当我单击一个项目时,它的颜色都会变为黄色。我在main活动中编写的OnClick函数。问题是,当我测试时,不仅那个项目改变了它的颜色,还有两个项目也改变了。我读到这是因为我重用了视图 所以我改变了策略,改用RecyclerView,但同样的问题也发生了。当我单击一个项目以更改其颜色时,下面的另一个项目也会更改。我想这是因为ListView和RecyclerView都重复使用了这些项目,所以当我
列表视图
和回收视图
最初,我创建了一个列表视图
,一切正常。然后我为它设置了onClick
事件,这样每当我单击一个项目时,它的颜色都会变为黄色。我在main活动中编写的OnClick
函数。问题是,当我测试时,不仅那个项目改变了它的颜色,还有两个项目也改变了。我读到这是因为我重用了视图
所以我改变了策略,改用RecyclerView
,但同样的问题也发生了。当我单击一个项目以更改其颜色时,下面的另一个项目也会更改。我想这是因为ListView
和RecyclerView
都重复使用了这些项目,所以当我单击其中一个时,它们会混淆
我不知道如何解决这个问题,我发现一个解决方案是添加一个boolean
数组,该数组标记单击的项目,但它不起作用。有什么想法吗,伙计们
这是代码
主要活动
class main活动:活动
{
公共回收视图回收视图;
公共RecyclerView.LayoutManager;
公共RecyclerView.适配器;
列表lst;
创建时受保护的覆盖无效(捆绑包)
{
base.OnCreate(bundle);
//从“主”布局资源设置视图
SetContentView(Resource.Layout.Main);
init();
recyclerView=(recyclerView)FindViewById(Resource.Id.recyclerView);
经理=新的LinearLayoutManager(本);
recyclerView.SetLayoutManager(管理器);
CustomAdapter=新的CustomAdapter(lst,this);
adapter.ItemClick+=onItemClick;
recyclerView.SetAdapter(适配器);
}
公共void init()
{
lst=新列表();
对于(int i=0;i<15;i++)
{
Row Row=新行(){field1=“1:43:00”,field2=“09-Apr-16”,field3=“KPI/Overflow”,field4=“Kevin Bacon”,field5=“无人”,field6=“人员计数@IPCAM-ID-C-1-1”};
第一次添加(行);
}
}
public void onItemClick(对象发送器,int位置)
{
int itemPos=位置+1;
//Toast.MakeText(this,“this is”+itemPos,ToastLength.Short).Show();
recyclerView.GetChildAt(position.SetBackgroundColor(Android.Graphics.Color.Green);
}
}
自定义适配器
公共类CustomAdapter:RecyclerView.Adapter
{
公共活动;;
公共列表lst;
公共事件事件处理程序项单击;
公共CustomAdapter(列表lst,活动)
{
这是1.lst=lst;
这个。_活动=活动;
}
公共覆盖int ItemCount
{
得到
{
返回一次计数;
}
}
公共void OnClick(内部位置)
{
如果(ItemClick!=null)
{
项目点击(此,位置);
}
}
公共覆盖无效OnBindViewHolder(RecyclerView.ViewHolder,int位置)
{
MyViewHolder myholder=作为MyViewHolder的持有人;
myholder.textView1.Text=lst[position].field1;
myholder.textView2.Text=lst[position].field2;
myholder.textView3.Text=lst[position].field3;
myholder.textView4.Text=lst[position].field4;
myholder.textView5.Text=lst[position].field5;
myholder.textView6.Text=lst[position].field6;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(视图组父级,int-viewType)
{
视图v=此._活动.LayoutInflater.充气(Resource.Layout.item,父项,false);
TextView tv1=(TextView)v.FindViewById(Resource.Id.textView1);
TextView tv2=(TextView)v.FindViewById(Resource.Id.textView2);
TextView tv3=(TextView)v.FindViewById(Resource.Id.textView3);
TextView tv4=(TextView)v.FindViewById(Resource.Id.textView4);
TextView tv5=(TextView)v.FindViewById(Resource.Id.textView5);
TextView tv6=(TextView)v.FindViewById(Resource.Id.textView6);
MyViewHolder=new MyViewHolder(v,OnClick){textView1=tv1,textView2=tv2,textView3=tv3,textView4=tv4,textView5=tv5,textView6=tv6};
报税表持有人;
}
}
类MyViewHolder:RecyclerView.ViewHolder
{
公共文本视图文本视图1、文本视图2、文本视图3、文本视图4、文本视图5、文本视图6;
公众观点;
公共MyViewHolder(视图、操作侦听器):基本(视图)
{
主视图=视图;
mainView.Click+=(发送者,e)=>listener(基本位置);
}
}
我遵循了Xamarin站点上的OnClic
k处理程序的示例
您的问题在于代码。您将正确的位置发送给事件处理程序,但随后在“活动”中将其递增1。两端应使用基于0的项目位置索引。没有必要增加1
要更改所选项目的背景色,可以使用XML中的选择器,这样就不需要在代码中执行此操作
这里有一个例子
行选择器.xml
row_content.axml
然后您的视图持有者将更新到此
class MyViewHolder : RecyclerView.ViewHolder
{
public TextView textView1, textView2, textView3, textView4, textView5, textView6;
public View mainView;
private LinearLayout _layoutParent;
public MyViewHolder(View view, Action<int> listener) : base(view)
{
mainView = view;
_layoutParent = mainView.FindViewById<LinearLayout>(Resource.Id.row_layout_parent);
_layoutParent.Click += (sender, e) => _layoutParent.Selected = true;
}
}
类MyViewHolder:RecyclerView.ViewHolder
{
公共文本视图文本视图1、文本视图2、文本视图3、文本视图4、文本视图5、文本视图6;
公众观点;
私人线路布局-布局母公司;
公共MyViewHolder(视图、操作侦听器):基本(视图)
{
主视图=视图;
_layoutParent=mainView.FindViewById(Resource.Id.row\u layout\u parent);
_放置
public class CustomAdapter : RecyclerView.Adapter
{
public Activity _activity;
public List<Row> lst;
public event EventHandler<int> ItemClick;
public CustomAdapter(List<Row> lst, Activity activity)
{
this.lst = lst;
this._activity = activity;
}
public override int ItemCount
{
get
{
return lst.Count;
}
}
public void OnClick(int position)
{
if (ItemClick!=null)
{
ItemClick(this, position);
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
MyViewHolder myholder = holder as MyViewHolder;
myholder.textView1.Text = lst[position].field1;
myholder.textView2.Text = lst[position].field2;
myholder.textView3.Text = lst[position].field3;
myholder.textView4.Text = lst[position].field4;
myholder.textView5.Text = lst[position].field5;
myholder.textView6.Text = lst[position].field6;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View v = this._activity.LayoutInflater.Inflate(Resource.Layout.item, parent, false);
TextView tv1 = (TextView)v.FindViewById(Resource.Id.textView1);
TextView tv2 = (TextView)v.FindViewById(Resource.Id.textView2);
TextView tv3 = (TextView)v.FindViewById(Resource.Id.textView3);
TextView tv4 = (TextView)v.FindViewById(Resource.Id.textView4);
TextView tv5 = (TextView)v.FindViewById(Resource.Id.textView5);
TextView tv6 = (TextView)v.FindViewById(Resource.Id.textView6);
MyViewHolder holder = new MyViewHolder(v, OnClick) { textView1 = tv1, textView2 = tv2, textView3 = tv3, textView4 = tv4, textView5 = tv5, textView6 = tv6 };
return holder;
}
}
class MyViewHolder : RecyclerView.ViewHolder
{
public TextView textView1, textView2, textView3, textView4, textView5, textView6;
public View mainView;
public MyViewHolder(View view, Action<int> listener) : base(view)
{
mainView = view;
mainView.Click += (sender, e) => listener(base.Position);
}
}
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/green" />
<item android:state_selected="false" android:color="@android:color/transparent"/>
</selector>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/row_layout_parent"
android:background="@drawable/row_selector">
<!-- your row content -->
</LinearLayout>
class MyViewHolder : RecyclerView.ViewHolder
{
public TextView textView1, textView2, textView3, textView4, textView5, textView6;
public View mainView;
private LinearLayout _layoutParent;
public MyViewHolder(View view, Action<int> listener) : base(view)
{
mainView = view;
_layoutParent = mainView.FindViewById<LinearLayout>(Resource.Id.row_layout_parent);
_layoutParent.Click += (sender, e) => _layoutParent.Selected = true;
}
}
listView.ChoiceMode = ChoiceMode.Single;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Support.V7.Widget;
using Android.Text;
using Android.Text.Style;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.Util.Zip;
using ActionMenuView = Android.Support.V7.Widget.ActionMenuView;
namespace Android.Basic.Core
{
public class GenericRecyclerViewAdapter<T> : RecyclerView.Adapter
{
/// <summary>
/// You can set this for different custom cardview
/// </summary>
private int CardViewResourceLayout { get; set; }
public ObservableCollection<T> Items { get; private set; }
public event EventHandler<RecyclerViewViewHolder> ItemViewTemplated;
public RecyclerView.LayoutManager layoutManager;
public GenericRecyclerViewAdapter(RecyclerView recyclerView, IEnumerable<T> items, int cardViewResourceLayout, bool isList = true, bool isVertical = true) : base()
{
if(isList)
{
var vertical = isVertical ? LinearLayoutManager.Vertical : LinearLayoutManager.Horizontal;
layoutManager = new LinearLayoutManager(recyclerView.Context, vertical, false);
}
else
{
var vertical = isVertical ? GridLayoutManager.Vertical : GridLayoutManager.Horizontal;
layoutManager = new GridLayoutManager(recyclerView.Context, 3, vertical, false);
}
recyclerView.SetLayoutManager(layoutManager);
this.Items = new ObservableCollection<T>(items);
this.CardViewResourceLayout = cardViewResourceLayout;
this.Items.CollectionChanged += delegate
{
this.NotifyDataSetChanged();
};
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
var itemView = LayoutInflater.From(parent.Context).Inflate(CardViewResourceLayout, parent, false);
#if DEBUG
Log.Info("GenericRecyclerViewAdapter - ", CardViewResourceLayout.ToString());
#endif
RecyclerViewViewHolder vh = new RecyclerViewViewHolder(itemView);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
RecyclerViewViewHolder vh = holder as RecyclerViewViewHolder;
vh.ItemPosition = position;
vh.TemplateView.Tag = position;
vh.TemplateView.Click -= TemplateView_Click;
vh.TemplateView.Click += TemplateView_Click;
ItemViewTemplated?.Invoke(this, vh);
}
public event EventHandler<T> ItemClicked;
private void TemplateView_Click(object sender, EventArgs e)
{
var position = (int)((View)sender).Tag;
this.ItemClicked?.Invoke(sender, this.Items[position]);
}
public override int ItemCount
{
get { return this.Items.Count; }
}
public override long GetItemId(int position)
{
return base.GetItemId(position);
}
}
public class RecyclerViewViewHolder : RecyclerView.ViewHolder, View.IOnCreateContextMenuListener,
IMenuItemOnMenuItemClickListener
{
public View TemplateView { get; private set; }
public int ItemPosition { get; set; }
public event EventHandler<MenuInfo> ContextMenuCreated;
public event EventHandler<object> MenuItemClicked;
public MenuInfo MenuInfo { get; private set; }
public object Data { get; set; }
public RecyclerViewViewHolder(View itemView) : base(itemView)
{
// Locate and cache view references:
this.TemplateView = itemView;
this.TemplateView.SetOnCreateContextMenuListener(this);
}
public void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
{
MenuInfo = new MenuInfo(menu, v, menuInfo);
ContextMenuCreated?.Invoke(this, MenuInfo);
}
private Android.Views.MenuInflater menuInflater = null;
/// <summary>
/// After ContextMenuCreated
/// </summary>
/// <param name="resourcemenu"></param>
public void InflateMenu(int resourcemenu, SpannableString titleColor = null, object dta = null)
{
if (dta != null)
this.Data = dta;
if (this.TemplateView.Context is AppCompatActivity activity)
{
menuInflater = activity.MenuInflater;
}
else if (this.TemplateView.Context is Activity activity2)
{
menuInflater = activity2.MenuInflater;
}
var contextMenu = this.MenuInfo.ContextMenu;
contextMenu.Clear();
menuInflater.Inflate(resourcemenu, contextMenu);
var num = contextMenu.Size() - 1;
for (int i = 0; i <= num; i++)
{
var men = contextMenu.GetItem(i);
if(titleColor != null)
{
if (i == 0)
{
men.SetTitle(titleColor);
men.SetChecked(true);
}
}
if (i != 0)
{
men.SetOnMenuItemClickListener(this);
}
}
}
public bool OnMenuItemClick(IMenuItem item)
{
this.MenuItemClicked?.Invoke(item, this.Data);
return true;
}
public float PosX;
public float PosY;
}
public class MenuInfo
{
public IContextMenu ContextMenu { get; }
public View View { get; }
public IContextMenuContextMenuInfo ContextMenuInfo { get; }
public MenuInfo(IContextMenu contextMenu, View view, IContextMenuContextMenuInfo menuInfo)
{
this.ContextMenu = contextMenu;
this.View = view;
this.ContextMenuInfo = menuInfo;
}
}
}
RecyclerView recyclerView = new RecyclerView(this);
var viewAdapter = new Android.Basic.Core.GenericRecyclerViewAdapter<Java.IO.File>(recyclerView, files, Resource.Layout.directory_item);
var indiColor = ThemeHelper.IsDark ? ColorHelper.GetRandomLightColor() : ColorHelper.GetRandomDarkColor();
viewAdapter.ItemViewTemplated += (dd, holder) =>
{
var file = files[holder.ItemPosition];
var view = holder.ItemView;
var expanded = view.FindViewById<ExpandedView>(Resource.Id.expandedView);
expanded.SetToggleColor(indiColor);
expanded.SetTitle(file.Name);
GenerateRecycler(expanded, file);
};
recyclerView.SetAdapter(viewAdapter);
expandedView.AddExpandedView(recyclerView);