Skip to content

Instantly share code, notes, and snippets.

@strombringer
Last active January 23, 2019 20:45
Show Gist options
  • Save strombringer/e35cc360402ac009d1fc0e351991b23b to your computer and use it in GitHub Desktop.
Save strombringer/e35cc360402ac009d1fc0e351991b23b to your computer and use it in GitHub Desktop.
Using a ContextMenu with MvxRecyclerView (Xamarin, MvvmCross, Android)
public class ContextMenuRecyclerViewAdapter : MvxRecyclerAdapter
{
private readonly Action<int> _contextPositionSetter;
public ContextMenuRecyclerViewAdapter(IMvxAndroidBindingContext bindingContext, Action<int> contextPositionSetter) : base(bindingContext)
{
_contextPositionSetter = contextPositionSetter;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
// the same code as in MvxRecyclerAdapter, we just supply our own ViewHolder class and set the _contextPositionSetter
var itemBindingContext = new MvxAndroidBindingContext(parent.Context, BindingContext.LayoutInflaterHolder);
var vh = new ContextMenuViewHolder(InflateViewForHolder(parent, viewType, itemBindingContext), itemBindingContext, _contextPositionSetter)
{
Click = ItemClick,
LongClick = ItemLongClick
};
return vh;
}
}
public class ContextMenuViewHolder : MvxRecyclerViewHolder, View.IOnCreateContextMenuListener
{
private readonly Action<int> _contextPositionSetter;
public ContextMenuViewHolder(View itemView, IMvxAndroidBindingContext context, Action<int> contextPositionSetter) : base(itemView, context)
{
itemView.SetOnCreateContextMenuListener(this);
_contextPositionSetter = contextPositionSetter;
}
public void OnCreateContextMenu(IContextMenu menu, View v, IContextMenuContextMenuInfo menuInfo)
{
// menuInfo is null when using it from RecyclerView, so we have to use the _contextPositionSetter
MenuInflater inflater = new MenuInflater(v.Context);
inflater.Inflate(Resource.Menu.my_context_menu, menu);
_contextPositionSetter?.Invoke(AdapterPosition);
}
}
public class MyFragmentView : MvxFragment<MyFragmentViewModel>
{
private MvxRecyclerView _list;
private int _contextMenuItemPosition;
public override bool OnContextItemSelected(IMenuItem item)
{
// item.MenuInfo is null when using it from RecyclerView, so we have to use _contextMenuItemPosition
var myItem = _list.Adapter.GetItem(_contextMenuItemPosition) as MyItem;
if (myItem != null)
{
switch (item.ItemId)
{
// TODO: handle relevant menu items and "return true;"
default:
break;
}
}
return base.OnContextItemSelected(item);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
base.OnCreateView(inflater, container, savedInstanceState);
var view = this.BindingInflate(Resource.Layout.my_fragment_layout, null);
_list = view.FindViewById<MvxRecyclerView>(Resource.Id.list);
// this action will be invoked every time a context menu is created and supplied with the item's position that created the menu
Action<int> contextMenuItemPositionSetter = (pos) => _contextMenuItemPosition = pos;
// explicitly using the fragment's BindingContext, because MvxAndroidBindingContextHelpers.Current() returns null
var adapter = new ContextMenuRecyclerViewAdapter((IMvxAndroidBindingContext)BindingContext, contextMenuItemPositionSetter);
_list.Adapter = adapter;
RegisterForContextMenu(_list);
return view;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment