在开始之前,您必须了解三件重要的事情:
1) 您必须编写自定义菜单控制器视图,但我猜您有点预料到了。我只知道自定义菜单控制器的commercial 实现,但这应该不会太难。
2) 在UIResponder 上有一个有用的方法叫做-canPerformAction:withSender:。在UIResponder Class Reference 中了解更多信息。您可以使用该方法来确定您的文本视图是否支持特定的标准操作(在UIResponderStandardEditActions 协议中定义)。
这在决定在自定义菜单控制器中显示哪些项目时很有用。例如,仅当用户的粘贴板包含要粘贴的字符串时,才会显示“粘贴”菜单项。
3)您可以通过收听UIMenuControllerWillShowMenuNotification 通知来检测UIMenuController 何时显示。
既然你都知道了,那么我将开始解决这个问题:
1) 在文本视图为第一响应者时监听UIMenuControllerWillShowMenuNotifications
- (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 或类似的东西。
这并不容易,但它是可行的,我希望它对你很有效。祝你好运!
更新:
今天 cocoacontrols.com 上出现了一个新的菜单实现,你可能想看看:https://github.com/questbeat/QBPopupMenu
更新 2:
正如this answer 中所述,您可以使用-caretRectForPosition: 获取文本视图的选定文本的框架。