我注意到RecyclerView.Adapter
中的Xamarin.Android
类型不是通用的。为什么会这样?根据{{3}},它似乎在原生Android中被定义为通用的。这有什么潜在的原因吗?或者它是某种向后兼容的场景?
答案 0 :(得分:0)
您可以在C#中创建通用的RecycleView,但不能在Java中创建。在Java中,您需要多次编写代码。这就是为什么Java android即使是简单的事件处理程序也更糟糕的原因,由于Java的本质,Android Team Engineers懒于实现所有数据事件处理。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.Widget;
using Android.Util;
using Android.Views;
using Android.Widget;
namespace XamarinAndroid.Basic.Core
{
public class GenericRecyclerViewAdapter<T> : RecyclerView.Adapter
{
/// <summary>
/// You can set this for different custom cardview
/// </summary>
public int CardViewResourceLayout { get; set; }
public ObservableCollection<T> Items { get; private set; }
public event EventHandler<RecyclerViewViewHolder> ItemViewTemplated;
public GenericRecyclerViewAdapter(IEnumerable<T> items, int cardViewResourceLayout) : base()
{
this.Items = new ObservableCollection<T>(items);
this.CardViewResourceLayout = cardViewResourceLayout;
this.Items.CollectionChanged += (sender, e) =>
{
try
{
this.NotifyDataSetChanged();
}
catch { }
};
}
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;
this.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(this, 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
{
public View TemplateView { get; private set; }
public int ItemPosition { get; set; }
public RecyclerViewViewHolder(View itemView) : base(itemView)
{
// Locate and cache view references:
this.TemplateView = itemView;
}
}
}
向每个视图分配数据
var recyclerViewToday = this.FindViewById<Android.Support.V7.Widget.RecyclerView>(Resource.Id.recyclerViewToday);
var layoutManager = new LinearLayoutManager(this);
recyclerViewToday.SetLayoutManager(layoutManager);
var adapter = new GenericRecyclerViewAdapter<FavoriteModel>(previousList, Resource.Layout.recent_list_item);
adapter.ItemViewTemplated += (d, holder) =>
{
var indicate = holder.ItemView.FindViewById<View>(Resource.Id.indicatorItemmRec);
indicate.SetBackgroundColor(ColorHelper.GetRandomLightColor());
(holder.ItemView.FindViewById<TextView>(Resource.Id.wordTxtRec)).Text = adapter.Items[holder.ItemPosition].Word;
var textView = (holder.ItemView.FindViewById<TextView>(Resource.Id.definitionTxtRec));
if (!string.IsNullOrEmpty(previousList[holder.ItemPosition].Definition))
textView.Text = previousList[holder.ItemPosition].Definition;
else
textView.Visibility = Android.Views.ViewStates.Gone;
};
recyclerViewToday.SetAdapter(adapter);
答案 1 :(得分:0)
干净、通用且可重复使用
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 = context.FindViewById<RecyclerView>(Resource.Id.recycler);
var viewAdapter = new Android.Basic.Core.GenericRecyclerViewAdapter<StorageFile>(recyclerView, files, Resource.Layout.main_item);
viewAdapter.ItemViewTemplated += (dd, holder) =>
{
//CardView
CardView cardView = holder.ItemView.FindViewById<CardView>(Resource.Id.CategorycardView);
cardView.SetCardBackgroundColor(ThemeHelper.IsDark ? Color.ParseColor("#303030") : Color.White);
var indicator = holder.ItemView.FindViewById<LinearLayout>(Resource.Id.indicator);
indicator.SetBackgroundColor(ThemeHelper.IsDark ? ColorHelper.GetRandomLightColor() : ColorHelper.GetRandomDarkColor());
var file = files[holder.ItemPosition];
var itemIcon = holder.ItemView.FindViewById<ImageView>(Resource.Id.itemIcon);
var icon = file.GetFileThumbnail();
if (icon != null)
{
itemIcon.SetImageBitmap(icon);
}
TextView itemName = holder.ItemView.FindViewById<TextView>(Resource.Id.itemName);
itemName.Text = file.DisplayName;
itemName.SetTextColor(textColor);
};
viewAdapter.ItemClicked += (dd, ff) =>
{
var checkBttn = (dd as View).FindViewById<ImageButton>(Resource.Id.check_boxBttn);
};
recyclerView.SetAdapter(viewAdapter);