2009-07-18 43 views
19

我试图让下面的代码工作:如何让UIMenuController为自定义视图工作?

UIMenuController * menu = [UIMenuController sharedMenuController]; 
[menu setTargetRect: CGRectMake(100, 100, 100, 100) inView: self.view]; 
[menu setMenuVisible: YES animated: YES]; 

菜单实例已准备就绪,但它并不显示 - 宽度始终为零。

或者是否有这UIPasteboard/UIMenuController主题上的一些示例代码?

回答

0

难道你不需要将UIMenuController* menu添加到主或子视图,E.G. self.view? 我认为这就像[self.view addSubView:menu.view];或者我错过了你的问题的重点。您可能还想设置菜单视图的框架。

0

UIMenuController没有视图。我只是搜查从苹果公司的iPhone Application Programming Guide: Event Handling一些代码:

清单3-4显示编辑菜单

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *theTouch = [touches anyObject]; 

    if ([theTouch tapCount] == 2 && [self becomeFirstResponder]) { 

     // selection management code goes here... 

     // bring up editing menu. 
     UIMenuController *theMenu = [UIMenuController sharedMenuController]; 
     CGRect selectionRect = CGRectMake(currentSelection.x, currentSelection.y, SIDE, SIDE); 
     [theMenu setTargetRect:selectionRect inView:self]; 
     [theMenu setMenuVisible:YES animated:YES]; 
    } 
} 
+0

评论有字符数限制 - 所以我在这里发布代码。 – 2009-07-18 07:19:10

+0

刚发现一个解决方法: 在视图中放入一个隐形的UITextField,并使其成为第一响应者。然后复制粘贴菜单将正确弹出。 – 2009-07-18 08:28:20

+0

我有这个相同的问题(我的自定义视图是UITableViewCell的一个子类;但否则它是相同的情况)。一个无形的UITextField不帮助我。菜单仍然没有显示,menuFrame仍然是全零。此外,只要我将UITextField设置为firstResponder,键盘就会弹出。你能为你的解决方案发布一些示例代码吗? – 2009-07-18 16:08:18

1
// MyView.h 

@interface MyView : UIView { 
    IBOutlet UITextField * textField_; 
} 

@end 

// MyView.m 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 
    NSLog(@"show menu"); 

    [textField_ becomeFirstResponder]; 
    // [self.window becomeFirstResponder]; 

    UIMenuController * menu = [UIMenuController sharedMenuController]; 
    [menu setTargetRect: CGRectMake(0, 0, 100, 10) inView: self]; 
    [menu setMenuVisible: YES animated: YES]; 

    NSLog(@"menu width %f, visible %d", menu.menuFrame.size.width, menu.menuVisible); 
} 

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

您需要在canPerformAction添加更多的代码:withSender: - 它应该检查粘贴板和您的选择状态。 Apple的iPhone应用程序编程指南提供了几个代码片段。

7

如果要实现自定义视图和观点应该是响应(相对于其他一些观点,像一个的UITextField),你需要重写canBecomeFirstResponder功能,在您的视图,并返回YES:

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 

那么,当你在显示菜单,你应该做的事情如下所示:

- (void)myMenuFunc { 
    if (![self becomeFirstResponder]) { 
     NSLog(@"couldn't become first responder"); 
     return; 
    } 

    UIMenuController *theMenu = [UIMenuController sharedMenuController]; 
    CGRect selectionRect = CGRectMake(0, 0, 0, 0); 
    [theMenu setTargetRect:selectionRect inView:self]; 
    [theMenu setMenuVisible:YES animated:YES]; 
} 
4

显示UIMenuController必须加上以下

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{ 
    if (action == @selector(cut:)) 
     return NO; 
    else if (action == @selector(copy:)) 
     return YES; 
    else if (action == @selector(paste:)) 
     return NO; 
    else if (action == @selector(select:) || action == @selector(selectAll:)) 
     return NO; 
    else 
     return [super canPerformAction:action withSender:sender]; 
} 
+0

你能告诉我如何在此添加Forward选项吗?我正在寻找它,所以帮助我..! – Vivek2012 2012-01-25 06:26:26

2

我觉得凸轮是正确的,需要同时覆盖canPerformAction和canBecomeFirstResponder

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

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 
48

我是不是能够得到,即使我读了所有你的答案它的工作。我正在提供适用于所有人的现成代码。

比方说,我们有一个名为控制器控制器类。您可以将下面的代码简单地粘贴到该控制器具有菜单视图工作:


- (void)loadView { 
    [super loadView]; 

    UILongPressGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; 
    [self.view addGestureRecognizer:gr];  
} 

- (void) longPress:(UILongPressGestureRecognizer *) gestureRecognizer { 
    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) { 
     CGPoint location = [gestureRecognizer locationInView:[gestureRecognizer view]]; 
     UIMenuController *menuController = [UIMenuController sharedMenuController]; 
     UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"Item" action:@selector(menuItemClicked:)]; 

     NSAssert([self becomeFirstResponder], @"Sorry, UIMenuController will not work with %@ since it cannot become first responder", self); 
     [menuController setMenuItems:[NSArray arrayWithObject:resetMenuItem]]; 
     [menuController setTargetRect:CGRectMake(location.x, location.y, 0.0f, 0.0f) inView:[gestureRecognizer view]]; 
     [menuController setMenuVisible:YES animated:YES]; 
    } 
} 

- (void) copy:(id) sender { 
    // called when copy clicked in menu 
} 

- (void) menuItemClicked:(id) sender { 
    // called when Item clicked in menu 
} 

- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender { 
    if (selector == @selector(menuItemClicked:) || selector == @selector(copy:)) { 
     return YES; 
    } 
    return NO; 
} 

- (BOOL) canBecomeFirstResponder { 
    return YES; 
} 

发生了什么,以便完成对菜单的工作就是firstResponder(在我们的例子中我们的控制器 - 看线与[自becomeFirstResponder])具有能够成为第一响应(重写方法canBecomeFirstResponder原因默认实现否)以及- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender应YES返回到可以由firstResponder

6

执行。在情况下有人仍然有任何动作问题:我的菜单曾经工作,有一天奇迹般地停止工作。我应用程序中的其他内容仍然有效。现在我已经从application:didFinishLaunchingWithOptions:方法中删除了[window makeKeyAndVisible]方法,而其他一切仍然有效,这会打破UIMenuController!在我身边

愚蠢的错误,很难找到罪魁祸首......

0

我做到了,在下面的下面的方式。只需调用在init中非常短暂的延迟后显示菜单的方法即可。我不想从View Controller中调用它,也没有找到表示我的自定义视图出现的事件,并且我已准备好显示菜单。所以从我的角度来看,这种方式是可行延迟可能会更少,但它取决于你。

@implementation DTSignatureImageView 

- (id)initWithImage:(UIImage *)image 
{ 
    self = [super initWithImage:image]; 
    if(self){ 
     self.contentMode = UIViewContentModeScaleAspectFit; 
     self.frame = CGRectMake(0, 0, image.size.width/2.5, image.size.height/2.5); 
     self.userInteractionEnabled = YES; 

     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(signatureDidPan:)]; 
     [self addGestureRecognizer:pan]; 

     [self becomeFirstResponder]; 

     [self performSelector:@selector(showMenu) withObject:nil afterDelay:0.5]; 
    } 

    return self; 
} 

- (BOOL)canBecomeFirstResponder 
{ 
    return YES; 
} 

- (void)showMenu 
{ 
    UIMenuController *menu = [UIMenuController sharedMenuController]; 
    menu.menuItems = @[ 
     [[UIMenuItem alloc] initWithTitle:@"Apply" action:@selector(applySignature)], 
     [[UIMenuItem alloc] initWithTitle:@"Update" action:@selector(updateSignature)], 
     [[UIMenuItem alloc] initWithTitle:@"Clear" action:@selector(delegateSignature)]]; 
    [menu setTargetRect:self.bounds inView:self]; 
    [menu setMenuVisible:YES animated:YES]; 
} 

- (NSArray *)menuActions 
{ 
    static NSArray *actions = nil; 
    if (actions == nil){ 
     actions = @[ 
        NSStringFromSelector(@selector(applySignature)), 
        NSStringFromSelector(@selector(updateSignature)), 
        NSStringFromSelector(@selector(delegateSignature))]; 
    } 

    return actions; 
} 

- (void) signatureDidPan: (UIPanGestureRecognizer *)gesture 
{ 
    switch (gesture.state) { 
     case UIGestureRecognizerStateBegan: { 
      [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES]; 
      break; 
     } 

     case UIGestureRecognizerStateEnded: { 
      [self becomeFirstResponder]; 
      [self showMenu]; 
     } 

     default: 
      break; 
    } 

    CGPoint point = [gesture locationInView:gesture.view.superview]; 
    gesture.view.center = point; 
}