在选择文本时,如何用自己的视图替换UIMenuController? [英] How could I replace UIMenuController with my own view when text is selected?

查看:103
本文介绍了在选择文本时,如何用自己的视图替换UIMenuController?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当选择文本时,默认情况下会弹出UIMenuController,其中包含剪切/复制/粘贴等。

When text is selected, by default a UIMenuController pops up with cut/copy/paste etc.

我想用自己的自定义视图替换它(看起来类似,但是两次高,以便我可以有两行按钮/自定义视图)。我怎么能这样做?

I'd like to replace this with my own custom view (similar looking, but twice as high so that I can have two rows of buttons/custom views). How can I do this?

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

I know there's no easy way. I'm expecting that if there's an easy solution, it won't be very elegant. The code can't use any private API either.

我真的,真的不必实现我自己的文本视图,重新实现文本选择和输入,以及重新实现放大视图只是所以我可以编写自己的UIMenuController克隆,如果有任何方法可以避免它。应用程序的界面非常重要,我可以替换UIMenuController,所以如果没有其他答案,那么我可能最终会这样做。如果有人能为我节省大量时间并提出另一种更简单的方法,我将非常感激!

I'd really, really rather not have to implement my own text view, reimplement text selection and input, and reimplement the magnifying view just so I can write my own UIMenuController clone if there's any way to avoid it. It's pretty important to the app's interface that I can replace the UIMenuController, so if there's no other answer then I may end up doing this. I'll be VERY grateful if anyone can save me a decent chunk of time and propose another, easier way of doing this!

推荐答案

在开始之前,您必须了解三件重要事项:

There are three important things you have to know before you can start:

1)您必须编写自定义菜单控制器视图,但我猜你有点期待。我只知道自定义菜单控制器的商业实现,但这不应该是太难了。

1) You'll have to write your custom menu controller view, but I guess you kinda expected that. I only know of a commercial implementation of a custom menu controller, but this shouldn't be too hard.

2) UIResponder 上有一个名为<$的有用方法C $ C> -canPerformAction:withSender:。在 UIResponder类参考中了解更多相关信息。您可以使用该方法确定文本视图是否支持特定的标准操作(在 UIResponderStandardEditActions 协议)。

这在决定在自定义菜单控制器中显示哪些项时非常有用。例如,只有当用户的粘贴板包含要粘贴的字符串时,才会显示粘贴菜单项。

2) There is a useful method on UIResponder called -canPerformAction:withSender:. Read more about it in the UIResponder Class Reference. You can use that method to determine whether your text view supports a specific standard action (defined in the UIResponderStandardEditActions protocol).
This will be useful when deciding which items to show in your custom menu controller. For example the Paste menu item will only be shown when the user's pasteboard contains a string to paste.

3)您可以检测到<将通过收听 UIMenuControllerWillShowMenuNotification 通知来显示code> UIMenuController 。

3) You can detect when the UIMenuController will be shown by listening to the UIMenuControllerWillShowMenuNotification notification.

既然你已经了解了所有这些,那就是我开始解决的问题:

Now that you know all of that, this is how I'd start tackling that:

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

1) Listen for UIMenuControllerWillShowMenuNotifications when the text view is first responder

- (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

2) Show your custom menu controller instead of the default 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 来显示您的自定义菜单,以便它可以与状态栏重叠。

Misc. 1) You can use a fullscreen UIWindow for showing your custom menu so it can overlap the status bar.

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

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

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

Misc. 2) For determining which menu items to show you can use the mentioned -canPerformAction:withSender:

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

其他。 3)你必须在演示窗口或类似的东西上使用 UITapGestureRecognizer 来自行解雇菜单。

Misc. 3) You'll have to handle dismissing the menu yourself by using a UITapGestureRecognizer on the presenting window or something like that.

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

This won't be easy, but it's doable and I hope it works out well for you. Good luck!

更新:

今天cocoacontrols.com上出现了一个新的菜单实现你可能想要退房: https://github.com/questbeat/QBPopupMenu

更新2:

这个答案你可以使用 -caretRectForPosition获取文本视图所选文本的框架:

这篇关于在选择文本时,如何用自己的视图替换UIMenuController?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆