Android Xamarin Forms中如何让OnActionModeStarted内的ActionMode.Menu正常工作?
解决思路
针对三星系统更新后文本选择上下文菜单添加自定义项失效的问题,可尝试以下方案:
调整
base方法调用顺序
部分定制系统会在base.OnActionModeStarted中重置菜单,将自定义菜单项的添加逻辑放在base调用之后,确保系统菜单初始化完成后再注入自定义内容:public override void OnActionModeStarted(ActionMode mode) { base.OnActionModeStarted(mode); // 先执行系统初始化逻辑 IMenu menu = mode.Menu; menu.Add("MItem1"); menu.Add("MItem2"); menu.Add("MItem3"); // 设置点击监听 menu.GetItem(0).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 0)); menu.GetItem(1).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 1)); menu.GetItem(2).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 2)); }使用MenuInflater加载菜单资源
直接调用menu.Add可能被三星定制系统拦截,改用标准菜单资源文件加载的方式,兼容性更强:- 在
Resources/menu下创建custom_selection_menu.xml:<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_item1" android:title="MItem1"/> <item android:id="@+id/menu_item2" android:title="MItem2"/> <item android:id="@+id/menu_item3" android:title="MItem3"/> </menu> - 在
OnActionModeStarted中加载资源:public override void OnActionModeStarted(ActionMode mode) { base.OnActionModeStarted(mode); MenuInflater inflater = mode.MenuInflater; inflater.Inflate(Resource.Menu.custom_selection_menu, mode.Menu); // 设置点击监听 mode.Menu.FindItem(Resource.Id.menu_item1).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 0)); mode.Menu.FindItem(Resource.Id.menu_item2).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 1)); mode.Menu.FindItem(Resource.Id.menu_item3).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 2)); }
- 在
延迟添加菜单项
三星系统可能在OnActionModeStarted执行时还未完成菜单的最终初始化,通过延迟任务给系统留足时间:public override void OnActionModeStarted(ActionMode mode) { base.OnActionModeStarted(mode); mode.PostDelayed(() => { IMenu menu = mode.Menu; menu.Add("MItem1"); menu.Add("MItem2"); menu.Add("MItem3"); // 设置点击监听 menu.GetItem(menu.Size() - 3).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 0)); menu.GetItem(menu.Size() - 2).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 1)); menu.GetItem(menu.Size() - 1).SetOnMenuItemClickListener(new MenuItemOnMenuItemClickListener(this, 2)); }, 100); }接管ActionMode回调逻辑
如果以上方案都无效,直接替换Label的默认ActionMode回调,完全接管菜单的创建和点击逻辑:// 在Label初始化时设置自定义回调 yourLabel.SetCustomSelectionActionModeCallback(new CustomSelectionCallback(this)); // 自定义回调类 private class CustomSelectionCallback : Java.Lang.Object, ActionMode.ICallback { private YourActivity _activity; public CustomSelectionCallback(YourActivity activity) { _activity = activity; } public bool OnCreateActionMode(ActionMode mode, IMenu menu) { mode.MenuInflater.Inflate(Resource.Menu.custom_selection_menu, menu); return true; } public bool OnPrepareActionMode(ActionMode mode, IMenu menu) => false; public bool OnActionItemClicked(ActionMode mode, IMenuItem item) { switch(item.ItemId) { case Resource.Id.menu_item1: // 执行MItem1对应的逻辑 mode.Finish(); return true; case Resource.Id.menu_item2: // 执行MItem2对应的逻辑 mode.Finish(); return true; case Resource.Id.menu_item3: // 执行MItem3对应的逻辑 mode.Finish(); return true; default: return false; } } public void OnDestroyActionMode(ActionMode mode) {} }
内容的提问来源于stack exchange,提问作者jho
相关产品推荐
相关产品推荐

