在开始之前,您必须了解三件重要的事情:
1)您必须编写自定义菜单控制器视图,但我猜您有点期望如此。我只知道一个商业的 http://www.cocoanetics.com/parts/dtmenucontroller/实现自定义菜单控制器,但这应该不会太难。
2)有一个有用的方法UIResponder
called -canPerformAction:withSender:
。阅读更多相关信息UIResponder 类参考 http://developer.apple.com/library/ios/#documentation/uikit/reference/UIResponder_Class/Reference/Reference.html。您可以使用该方法来确定您的文本视图是否支持特定的标准操作(在UIResponder标准编辑操作 http://developer.apple.com/library/ios/#documentation/uikit/reference/UIResponderStandardEditActions_Protocol/UIResponderStandardEditActions.html协议)。
当决定在自定义菜单控制器中显示哪些项目时,这将很有用。例如,仅当用户的粘贴板包含要粘贴的字符串时,才会显示“粘贴”菜单项。
3)您可以检测到UIMenuController
将通过聆听来显示UIMenuControllerWillShowMenuNotification
通知。
现在你已经知道了所有这些,这就是我开始解决这个问题的方法:
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];
}
Misc. 1)您可以使用全屏UIWindow
用于显示您的自定义菜单,以便它可以与状态栏重叠。
UIWindow *presentingWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
presentingWindow.windowLevel = UIWindowLevelStatusBar + 1;
presentingWindow.backgroundColor = [UIColor clearColor];
[presentingWindow addSubview:controller];
[presentingWindow makeKeyAndVisible];
Misc. 2)要确定要显示哪些菜单项,您可以使用提到的-canPerformAction:withSender:
BOOL canPaste = [textView canPerformAction:@selector(paste:) withSender:nil];
BOOL canSelectAll = [textView canPerformAction:@selector(selectAll:) withSender:nil];
Misc. 3)您必须使用以下方法自行处理关闭菜单UITapGestureRecognizer
在呈现窗口或类似的东西上。
这并不容易,但它是可行的,我希望它对你有用。祝你好运!
Update:
今天,cocoacontrols.com 上弹出了一个新的菜单实现,您可能想查看一下:https://github.com/questbeat/QBPopupMenu https://github.com/questbeat/QBPopupMenu
更新2:
正如中所解释的这个答案 https://stackoverflow.com/questions/8683848/how-can-i-get-the-selected-text-frame-from-a-uitextview/8684006#8684006您可以使用以下命令获取文本视图所选文本的框架-caretRectForPosition:
.