如何select文本时用我自己的视图replaceUIMenuController?

当select文本时,UIMenuController默认popup剪切/复制/粘贴等。

在这里输入图像说明

我想用我自己的自定义视图(类似看,但两倍高,以便我可以有两行button/自定义视图)replace此。 我怎样才能做到这一点?

我知道有没有简单的方法。 我期待如果有一个简单的解决scheme,它不会很优雅。 该代码也不能使用任何私人API。

我真的,而不是必须实现我自己的文本视图,重新实现文本select和input,并重新实现放大视图,所以我可以编写自己的UIMenuController克隆,如果有任何方法来避免它。 应用程序的界面非常重要,我可以replaceUIMenuController,所以如果没有其他答案,那么我可能会做这个。 如果有人能为我节省很多时间,我会非常感激,并提出另一个更简单的方法来做到这一点!

在开始之前,你必须知道三件重要的事情:

1)你将不得不编写自定义的菜单控制器视图,但我想你有点期待。 我只知道一个自定义菜单控制器的商业实现,但这不应该太难。

2)UIResponder上有一个有用的方法叫做-canPerformAction:withSender: 在UIResponder类参考中阅读更多关于它的内容。 您可以使用该方法来确定您的文本视图是否支持特定的标准操作(在UIResponderStandardEditActions协议中定义)。
这在决定在自定义菜单控制器中显示哪些项目时很有用。 例如,只有当用户的粘贴板包含要粘贴的string时,“粘贴”菜单项才会显示。

3)您可以通过侦听UIMenuControllerWillShowMenuNotification通知来检测UIMenuController何时显示。

现在你知道所有这一切,这就是我开始解决这个问题的方法:

1)当文本视图是第一响应者时,监听UIMenuControllerWillShowMenuNotification

 - (void)textViewDidBeginEditing:(UITextView *)textView { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuWillBeShown:) name:UIMenuControllerWillShowMenuNotification object:nil]; } - (void)textViewDidEndEditing:(UITextView *)textView { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillShowMenuNotification object:nil]; } 

2)显示您的自定义菜单控制器,而不是默认的UIMenuController

 - (void)menuWillBeShown:(NSNotification *)notification { CGRect menuFrame = [[UIMenuController sharedMenuController] menuFrame]; [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO]; // Don't show the default menu controller CustomMenuController *controller = ...; controller.menuItems = ...; // additional stuff goes here [controller setTargetRectWithMenuFrame:menuFrame]; // menuFrame is in screen coordinates, so you might have to convert it to your menu's presenting view/window/whatever [controller setMenuVisible:YES animated:YES]; } 

杂项。 1)您可以使用全屏UIWindow来显示您的自定义菜单,以便它可以重叠状态栏。

 UIWindow *presentingWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; presentingWindow.windowLevel = UIWindowLevelStatusBar + 1; presentingWindow.backgroundColor = [UIColor clearColor]; [presentingWindow addSubview:controller]; [presentingWindow makeKeyAndVisible]; 

杂项。 2)确定要显示的菜单项可以使用提到的-canPerformAction:withSender:

 BOOL canPaste = [textView canPerformAction:@selector(paste:) withSender:nil]; BOOL canSelectAll = [textView canPerformAction:@selector(selectAll:) withSender:nil]; 

杂项。 3)您必须通过在演示窗口上使用UITapGestureRecognizer或类似的东西来UITapGestureRecognizer菜单问题。

这并不容易,但它是可行的,我希望它适合你。 祝你好运!

更新:
今天在cocoacontrols.com上popup一个新的菜单实现,你可能想看看: https : //github.com/questbeat/QBPopupMenu

更新2:
正如在这个答案中所解释的,你可以使用-caretRectForPosition:来获得文本视图的选定文本的-caretRectForPosition:

我认为这可能会帮助你https://github.com/cxa/UIMenuItem-CXAImageSupport

UIMenuItem使用UILabel来显示它的标题,这意味着我们可以swizzle -drawTextInRect:来支持图像。

UIMenuItem + CXAImageSupport是一个肮脏的黑客,但在大多数情况下应该是安全的。 不包含任何私人API。

为UIMenuItem创build一个类别而不是子类化,可以获得更多的灵活性。 是的,这个类别也可以应用到真棒PSMenuItem!

在这里输入图像说明