2010-06-24 63 views
55

我想创建一个自定义的UIMenuController并在我的视图中显示它。这里是我的代码:UIMenuController没有显示

UIMenuController *menuController = [UIMenuController sharedMenuController]; 
    UIMenuItem *listMenuItem = [[UIMenuItem alloc] initWithTitle:@"List" action:@selector(addList:)]; 

    [menuController setMenuItems:[NSArray arrayWithObject:listMenuItem]]; 
    [menuController setTargetRect:CGRectMake(50.0, 50.0, 0, 0) inView:self.view]; 
    [menuController setMenuVisible:YES animated:YES]; 

    [listMenuItem release]; 

没有错误或异常,但菜单控制器不显示。

回答

142

你需要做三件事情:

  1. 你需要调用视图或视图控制器-becomeFirstResponder
  2. 您的视图或视图控制器需要执行-canBecomeFirstResponder(返回YES)。
  3. (可选)您的视图或视图控制器可以实现-canPerformAction:action withSender:sender以独立显示/隐藏菜单项。
+2

乐于助人,非常有帮助。 – Jake 2011-09-06 15:03:06

+0

这在MonoTouch中的效果非常好 - 只有要注意的事情是'CanBecomeFirstResponder'是一个属性重写,并且您必须为'UIMenuController.MenuItems'属性指定一个'UIMenuItem []'数组。 – PaulJ 2012-05-10 08:45:58

+4

当我在视图*上调用'becomeFirstResponder' *时没有工作。在控制器上调用它工作得很好。 – 2013-04-15 17:02:26

-1

可能是因为CGRectMake(50.0, 50.0, 0, 0)创建了一个CGRectwidth = 0height = 0

欢呼声, 安卡

+0

即使我将宽度/高度设置为100,仍然不显示。 – indragie 2010-06-24 19:22:29

+0

好吧,你可以尝试添加方法(BOOL)canPerformAction:(SEL)action withSender:(id)sender并返回YES。 – anka 2010-06-24 19:37:45

+0

仍然无法使用。 – indragie 2010-06-24 19:50:07

15

UIMenuController是仅如果视图是第一响应和

任何视图中可见

- (BOOL)canPerformAction方法返回YES

因此,如果您的菜单控制器是上按钮点击被显示,在该第一线按钮操作应该是[self becomeFirstResponder]。注意:这里的自我是将呈现菜单的视图。

如果你的菜单上长按手势显示,然后写

[menuController setTargetRect:CGRectMake(50.0, 50.0, 0, 0) inView:self.view]; 
[menuController setMenuVisible:YES animated:YES]; 

[self becomeFirstResponder];

然后遵循OZ提到的步骤前添加longPressGesture到UIView,并在长按事件。

+0

我试过这个,但它不适合我。由于评论有限制我创建了另一个问题http://stackoverflow.com/questions/16054050/uimenucontroller-not-getting-displayed – JiteshW 2013-04-17 07:33:43

+0

谢谢,targetRect为我做了诡计。奇怪,因为我有另一个几乎完全相同的类,没有它就可以正常工作。 – Kalle 2013-08-09 12:05:55

2

为了防止任何人在使用iOS6时特别(和随机)出现此问题:您可能需要查看this SO与设备上启用“说话选择”(设置 - >常规 - >辅助功能 - >说话选择:开)。少数我的用户无法看到自定义UIMenuItems,这是原因。

4

以下是一个完整的评论工作示例...

查看子类的头文件

#import <Foundation/Foundation.h> 

@interface MenuControllerSupportingView : UIView 
{ 

} 
@end 

查看子类的源文件

#import "MenuControllerSupportingView.h" 

@implementation MenuControllerSupportingView 

//It's mandatory and it has to return YES then only u can show menu items.. 
-(BOOL)canBecomeFirstResponder 
{ 
    return YES; 
} 

-(void)MenuItemAClicked 
{ 
    NSLog(@"Menu item A clicked"); 
} 

-(void)MenuItemBClicked 
{ 
NSLog(@"Menu item B clicked"); 
} 

-(void)MenuItemCClicked 
{ 
    NSLog(@"Menu item C clicked"); 
} 

//It's not mandatory for custom menu items 

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{ 
    if(action == @selector(MenuItemAClicked)) 
    return YES; 
    else if(action == @selector(MenuItemBClicked)) 
    return YES; 
    else if(action == @selector(MenuItemCClicked)) 
    return YES; 
    else 
    return NO; 
} 

视图控制器头文件

#import <UIKit/UIKit.h> 

@interface ViewController1 : UIViewController 

@end 

视图控制器源码文件

#import "ViewController1.h" 
#import "MenuControllerSupportingView.h" 

@interface ViewController1() 
{ 
MenuControllerSupportingView *vu; 
} 
@end 

@implementation ViewController1 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    vu=[[SGGI_MenuControllerSupportingView alloc]initWithFrame:CGRectMake(0,0,768,1024)]; 

[self.view addSubview:vu]; 

UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom]; 

[btn setFrame:CGRectMake(200,200,200,30)]; 

[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 

[btn setTitle:@"Show" forState:UIControlStateNormal]; 

[btn addTarget:self action:@selector(SHowMenu) forControlEvents:UIControlEventTouchUpInside]; 

[vu addSubview:btn]; 

} 

-(void)SHowMenu 
{ 
UIMenuController *menucontroller=[UIMenuController sharedMenuController]; 

UIMenuItem *MenuitemA=[[UIMenuItem alloc] initWithTitle:@"A" action:@selector(MenuItemAClicked)]; 

UIMenuItem *MenuitemB=[[UIMenuItem alloc] initWithTitle:@"B" action:@selector(MenuItemBClicked)]; 

UIMenuItem *MenuitemC=[[UIMenuItem alloc] initWithTitle:@"C" action:@selector(MenuItemCClicked)]; 

[menucontroller setMenuItems:[NSArray arrayWithObjects:MenuitemA,MenuitemB,MenuitemC,nil]]; 

    //It's mandatory 
[vu becomeFirstResponder]; 

    //It's also mandatory ...remeber we've added a mehod on view class 
if([vu canBecomeFirstResponder]) 
{ 

    [menucontroller setTargetRect:CGRectMake(10,10, 0, 200) inView:vu]; 

    [menucontroller setMenuVisible:YES animated:YES]; 
} 

} 




-(void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 

} 

@end 

在View类如果u写canPerformAction是独自返回你会看到所有默认的菜单项类似相机的象征,剪切,复制等。

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{ 
return YES; 
} 

如果u想独自显示类似相机然后

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{ 
if([email protected](_insertImage:)) 
    return YES; 
else 
    return NO; 

} 

如果u想知道,那么所有的行动

参观link

13

答案提到三件事,但挑剔,有六种:

  1. 菜单处理程序必须是一个UIView。如果不是,则-becomeFirstResponder失败。
  2. 的菜单句柄必须userInteractionEnabled = YES
  3. 菜单处理程序必须在视图层次及其-window属性必须是一样的窗口中inView:争论的观点。
  4. 您需要执行-canBecomeFirstResponder并返回YES
  5. 您需要致电[handler becomeFirstResponder],[menu setTargetRect:inView:]被调用,否则后者将失败。
  6. 您需要致电[menu setTargetRect:inView](至少一次)和[menu setMenuVisible:animated:]

特别是上面的1-3点让我受不了。我想要一个自定义菜单处理程序类,最初是UIResponder,这导致-becomeFirstResponder返回NO;那么它是一个UIView,它失败了,然后我试图使它成为UIButton工作,但只是因为userInteractionEnabled默认为YES按钮和NOUIView s。

+1

这应该是公认的答案。 – Grimxn 2017-03-24 19:03:56

0

在雨燕3.0 -

在我来说,我想有VC预先选择一个TextView的文本,显示自定义的菜单供用户承担这种选择的动作。如所述,Kalle,订单非常重要,特别是最后制作setMenuVisible

在VC,viewDidLoad

menuCont = UIMenuController.shared 
let menuItem1: UIMenuItem = UIMenuItem(title: "Text", action: #selector(rtfView.textItem(_:))) 
let menuItems: NSArray = [menuItem1] 
menuCont.menuItems = menuItems as? [UIMenuItem] 

在VC中,当用户点击一个按钮:

@IBAction func pressed(_ sender: Any) { 
    self.textView.selectedRange = NSMakeRange(rangeStart, rangeLength) 
    self.textView.becomeFirstResponder() 
    menuCont.setTargetRect(CGRect.zero, in: self.textView) 
    menuCont.setMenuVisible(true, animated: true) 
} 

最后,在子类中的TextView的:

class rtfView: UITextView { 

override var canBecomeFirstResponder: Bool { 
    return true 
} 

override func canPerformAction(_ action: Selector, withSender sender: Any!) -> Bool { 
    if (action == #selector(textItem(_:))) { 
     return true 
    } else { 
     return false 
    } 
    } 
}