关于iPhone:选择文本后,如何用自己的视图替换UIMenuController?

How could I replace UIMenuController with my own view when text is selected?

当文本被选择时,默认情况下,与UIMenuController剪切/复制弹出/粘贴等

enter


开始之前,您必须了解三件事:

1)您必须编写您的自定义菜单控制器视图,但是我想您有点期望。我只知道自定义菜单控制器的商业实现,但这并不难。

2)UIResponder上有一个有用的方法,称为-canPerformAction:withSender:。在UIResponder类参考中阅读有关它的更多信息。您可以使用该方法来确定您的文本视图是否支持特定的标准操作(在UIResponderStandardEditActions协议中定义)。
当决定要在自定义菜单控制器中显示哪些项目时,这将非常有用。例如,仅当用户的粘贴板包含要粘贴的字符串时,才会显示"粘贴"菜单项。

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

现在您已经了解了所有这些,这就是我要开始解决的方式:

1)文本视图为第一响应者时收听UIMenuControllerWillShowMenuNotification s

1
2
3
4
5
6
7
- (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

1
2
3
4
5
6
7
8
9
10
11
12
- (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来显示您的自定义菜单,以便它可以与状态栏重叠。

1
2
3
4
5
6
UIWindow *presentingWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
presentingWindow.windowLevel = UIWindowLevelStatusBar + 1;
presentingWindow.backgroundColor = [UIColor clearColor];

[presentingWindow addSubview:controller];
[presentingWindow makeKeyAndVisible];

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

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

其他。 3)您必须自己使用显示窗口上的UITapGestureRecognizer或类似的方法来处理菜单。

这并非易事,但这是可行的,我希望对您来说很好。祝你好运!

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

更新2:
如此答案中所述,您可以使用-caretRectForPosition:

获取文本视图的选定文本的框架。


我认为这可能对您有所帮助https://github.com/cxa/UIMenuItem-CXAImageSupport

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

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

使类别成为UIMenuItem的子类,而不是为其子类化,将获得更大的灵活性。是的,该类别也可以应用于超棒的PSMenuItem!

enter