自定义 UIMenuController

Posted

技术标签:

【中文标题】自定义 UIMenuController【英文标题】:Customize UIMenuController 【发布时间】:2009-10-22 02:22:34 【问题描述】:

您好,我想在 iPhone SDK3.x 中创建自定义气泡菜单,例如剪切/复制/粘贴菜单。我知道它是 UIMenuController 但它只提供标准的剪切/复制/过去菜单。任何人都知道如何制作类似这样的气泡菜单。任何示例和代码供参考?

【问题讨论】:

【参考方案1】:

1) 您需要将自定义菜单项添加到共享的 UIMenuController:

UIMenuItem* miCustom1 = [[[UIMenuItem alloc] initWithTitle: @"Custom 1" action:@selector( onCustom1: )] autorelease];
UIMenuItem* miCustom2 = [[[UIMenuItem alloc] initWithTitle: @"Custom 2" action:@selector( onCustom2: )] autorelease];
UIMenuController* mc = [UIMenuController sharedMenuController];
mc.menuItems = [NSArray arrayWithObjects: miCustom1, miCustom2, nil];

2) 您需要在响应者链中的某处实现处理程序方法,以便在您显示菜单时成为第一响应者:

- (void) onCustom1: (UIMenuController*) sender



- (void) onCustom2: (UIMenuController*) sender


3) 您可以选择在响应者链中实现 canPerformAction:,以便在您显示菜单时作为第一响应者的视图:

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender

    if ( action == @selector( onCustom1: ) )
    
            return YES; // logic here for context menu show/hide
    

    if ( action == @selector( onCustom2: ) )
    
            return NO;  // logic here for context menu show/hide
    

    if ( action == @selector( copy: ) )
    
             // turn off copy: if you like:
        return NO;
    

    return [super canPerformAction: action withSender: sender];

4) 如果您要为其显示菜单的视图尚不支持显示菜单,(即 UIWebView 将在用户长按时显示菜单,但 UILabel 没有内置支持显示菜单),那么您需要自己显示菜单。这通常通过将 UILongPressGestureRecognizer 附加到视图来完成,然后在回调中显示菜单:

UILongPressGestureRecognizer* gr = [[[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector( onShowMenu: ) ] autorelease];
   [_myview addGestureRecognizer: gr];



- (void) onShowMenu: (UIGestureRecognizer*) sender

    [sender.view becomeFirstResponder];

    UIMenuController* mc = [UIMenuController sharedMenuController];

    CGRect bounds = sender.view.bounds;

    [mc setTargetRect: sender.view.frame inView: sender.view.superview];
    [mc setMenuVisible: YES animated: YES];

注意,必须有一个声明 firstResponder 的视图才能显示菜单。

5) 确保您显示菜单的视图返回 YES/TRUE 到 canBecomeFirstResponder。例如,如果您尝试将 UILabel 作为第一响应者,它将返回 NO,因此您必须对其进行子类化。

6) 就是这样。您可能希望在调用操作回调时 resignFirstResponder - 但要做到这一点,您需要实现逻辑来发现 firstResponder。

【讨论】:

canPerformAction 中的发件人不代表菜单出现在/上的对象(在我的情况下是文本视图) - 知道为什么吗? -[FirstViewController handleGesture::]: unrecognized selector sent to instance 0x1e865800 用于网页上的焦点元素。如何解决这个问题?当页面内没有元素专注于输入文本时,此方法确实有效。【参考方案2】:

使用 UIMenuController 上的 menuItems 属性。

【讨论】:

一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助

以上是关于自定义 UIMenuController的主要内容,如果未能解决你的问题,请参考以下文章

自定义UI 自定义布局

自定义UI 自定义布局

自定义UI 自定义布局

自定义 view - 自定义属性

Springboot+自定义注解+自定义AOP前置增强+自定义异常+自定义异常捕获

Android 自定义View