【问题标题】:How to get UIMenuController work for a custom view?如何让 UIMenuController 为自定义视图工作?
【发布时间】:2010-11-11 21:46:42
【问题描述】:

我正在尝试使以下代码工作:

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

菜单实例已准备好但未显示 - 宽度始终为零。

或者有没有关于这个UIPasteboard/UIMenuController主题的示例代码?

【问题讨论】:

    标签: iphone cocoa-touch iphone-sdk-3.0 uimenucontroller


    【解决方案1】:

    即使阅读了您的所有答案,我也无法使其正常工作。我正在展示适用于所有人的现成代码。

    假设我们有一个名为 Controller 的控制器类。您可以简单地将以下代码粘贴到此控制器,以使菜单在其视图上工作:

    
    - (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(在我们的例子中是我们的控制器 - 参见 [self becomeFirstResponder] 行)必须能够成为第一响应者(覆盖方法 canBecomeFirstResponder 导致默认实现返回 NO ) 以及- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender 应该对firstResponder 可以执行的任何操作返回YES

    【讨论】:

    • 您可能想要更改该断言以使用 canBecomeFirstResponder,并将 becomeFirstResponder 放在断言之外;)
    • 这非常有效。起初我有点担心 [self becomeFirstResponder] 会调出键盘,但事实并非如此。谢谢!
    • 复制方法中,如何获取选中的文本?复制到 UIPasteboard
    【解决方案2】:

    如果您正在实现自定义视图并且该视图应该是响应者(与其他视图相反,例如 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];
    }
    

    【讨论】:

      【解决方案3】:

      万一有人仍然有问题:我的菜单曾经可以工作,但有一天却奇迹般地停止工作。我的应用程序中的其他所有内容仍然有效。现在我已经从application:didFinishLaunchingWithOptions: 方法中删除了[window makeKeyAndVisible] 方法,虽然其他一切仍然有效,但这会破坏UIMenuController

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

      【讨论】:

      • 谢谢你。原来它发生在我身上,不知道 makeKeyAndVisible 线是如何被删除的,但没有它我几乎毁掉了我的显示器并用它的锋利边缘来提交 Hari-Kari。
      • 非常感谢。我在自己的窗口中展示了一个放大镜,并且需要再次设置主窗口键,以便 UIMenuController 工作。
      【解决方案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];
      }
      

      【讨论】:

      • 你能告诉我如何在这个中添加转发选项吗?我正在寻找它,所以请帮助我..!
      【解决方案5】:

      我认为 Cam 是对的,需要同时覆盖 canPerformAction 和 canBecomeFirstResponder

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

      【讨论】:

        【解决方案6】:
        // 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 应用程序编程指南提供了几个代码 sn-ps。

        【讨论】:

          【解决方案7】:

          您不必将UIMenuController* menu 添加到主视图或子视图,例如self.view? 我认为这类似于[self.view addSubView:menu.view]; 或者我错过了你的问题的重点。您可能还想设置菜单视图的框架。

          【讨论】:

            【解决方案8】:

            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];
                }
            }
            

            【讨论】:

            • 评论有字符限制 - 所以我在这里发布代码。
            • 刚刚找到一个解决方法:在视图中放置一个不可见的 UITextField,并使其成为第一响应者。然后复制粘贴菜单将正确弹出。
            • 我遇到了同样的问题(我的自定义视图是 UITableViewCell 的子类;但除此之外情况相同)。一个不可见的 UITextField 对我没有帮助。菜单仍未显示,menuFrame 仍为全零。此外,每当我将 UITextField 设置为 firstResponder 时,都会弹出键盘。您可以发布一些示例代码来解决您的问题吗?
            【解决方案9】:

            我是通过以下方式完成的。只需在很短的初始化延迟后调用显示菜单的方法。我不想从视图控制器调用它,也没有找到表明我的自定义视图出现并且我准备好显示菜单的事件。所以从我的角度来看,这样就可以了。延迟可以减少,但这取决于您。

            @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;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-04-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-14
              • 1970-01-01
              • 2014-04-05
              相关资源
              最近更新 更多