UIMenuController 未显示

发布于 2024-09-06 18:27:58 字数 527 浏览 4 评论 0原文

我正在尝试创建一个自定义 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];

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

I'm trying to create a custom UIMenuController and display it in my view. Here's my code:

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

There are no errors or exceptions, but the menu controller just doesn't show up.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

你与清晨阳光 2024-09-13 18:27:58

您需要做三件事:

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

You need to do three things:

  1. You need to call -becomeFirstResponder on the view or view controller.
  2. Your view or view controller needs to implement -canBecomeFirstResponder (returning YES).
  3. Optionally, your view or view controller can implement -canPerformAction:action withSender:sender to show/hide menu items on an individual basis.
慈悲佛祖 2024-09-13 18:27:58

答案提到了三件事,但要挑剔的话,有六件事:

  1. 菜单处理程序必须是 UIView。如果不是,-becomeFirstResponder 将失败。
  2. 菜单处理程序必须具有 userInteractionEnabled = YES
  3. 菜单处理程序必须位于视图层次结构中,并且其 -window 属性必须与 中视图的窗口相同>inView: 参数。
  4. 您需要实现-canBecomeFirstResponder并返回YES
  5. 您需要在调用[menu setTargetRect:inView:]之前调用[handlerBecomeFirstResponder],否则后者会失败。
  6. 您需要调用[menu setTargetRect:inView](至少一次)和[menu setMenuVisible:animated:]

特别是上面的 1-3 点让我很感动。我想要一个自定义菜单处理程序类,该类最初是 UIResponder,这导致 -becomeFirstResponder 返回 NO;然后它是一个UIView,失败了,然后我尝试将它设为一个UIButton,它起作用了,但只是因为userInteractionEnabled默认为YES 对于按钮,NO 对于 UIView

The answer mentions three things, but to be picky, there are six:

  1. The menu handler must be a UIView. If it isn't, -becomeFirstResponder fails.
  2. The menu handler must have userInteractionEnabled = YES
  3. The menu handler must be in the view hierarchy and its -window property must be the same as the window for the view in the inView: argument.
  4. You need to implement -canBecomeFirstResponder and return YES.
  5. You need to call [handler becomeFirstResponder], before [menu setTargetRect:inView:] is called, or the latter will fail.
  6. You need to call [menu setTargetRect:inView] (at least once) and [menu setMenuVisible:animated:].

In particular points 1-3 above got me. I wanted a custom menu handler class that was a UIResponder at first, which caused -becomeFirstResponder to return NO; then it was a UIView, which failed, then I tried making it a UIButton which worked, but only because userInteractionEnabled defaults to YES for buttons and NO for UIViews.

作妖 2024-09-13 18:27:58

仅当视图是第一响应者并且

- (BOOL)canPerformAction 方法返回 YES

因此,如果您的菜单控制器是单击按钮时显示,按钮操作中的第一行应为 [self comeFirstResponder]。注意:这里 self 是显示菜单的视图。

如果您的菜单要在长按手势上显示,请将 longPressGesture 添加到 UIView 并在长按事件中写入

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

[self comeFirstResponder];

然后按照提到的步骤操作由奥兹。

UIMenuController is visible on any view only if the view is first responder and

- (BOOL)canPerformAction method returns YES

Hence if your menu controller is to be shown on button click, the first line in the button action should be [self becomeFirstResponder]. NOTE: here self is the view which will present the menus.

If your menus are to be shown on long press gesture, then add longPressGesture to the UIView and in the longpress event before writing

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

write [self becomeFirstResponder];

Then follow the steps mentioned by OZ.

脱离于你 2024-09-13 18:27:58

下面是一个完整的注释工作示例...

查看子类头文件

#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 类中,如果您在 canPerformAction 中单独写入返回 YES,您将看到所有默认菜单项,如相机符号、剪切、复制等。

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

如果您想单独显示相机之类的内容,那么

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

}

如果您想了解所有操作,

请访问 链接

The below is a full commented working example ...

View subclass header file

#import <Foundation/Foundation.h>

@interface MenuControllerSupportingView : UIView
{

}
@end

View subclass source file

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

view Controller header file

#import <UIKit/UIKit.h>

@interface ViewController1 : UIViewController

@end

view Controller source file

 #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

In View class if u write return YES alone in canPerformAction you will see all the default menuitems like camera symbol,cut,copy etc..

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

if u want to show something like camera alone then

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

}

if u want to know about all the actions then

visit the link

街角卖回忆 2024-09-13 18:27:58

以防万一有人在 iOS6 上特别(随机)遇到此问题:您可能需要查看与在设备上启用朗读选择(设置 -> 常规 -> 辅助功能 -> 朗读选择:打开)。我的一小部分用户无法看到自定义 UIMenuItems,这就是原因。

Just in case anyone is having this issue specifically (and randomly) with iOS6: you might want to look at this SO related to having Speak Selection enabled on the device (Settings -> General -> Accessibility -> Speak Selection: On). A small number of my users were not able to see the custom UIMenuItems and this was the cause.

蓝色星空 2024-09-13 18:27:58

在 Swift 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
    }
  }
}

In Swift 3.0 -

In my case I wanted to have the VC pre-select the text in a TextView and display a custom menu for the user to take action on that selection. As mentioned by Kalle, order is very important, especially making setMenuVisible last.

In VC, viewDidLoad:

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

In VC, when the user hits a button:

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

Finally, in the sub-class of the 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
    }
  }
}
乜一 2024-09-13 18:27:58

可能是因为 CGRectMake(50.0, 50.0, 0, 0) 创建了一个 CGRect,其中 width = 0height = 0 >?

干杯,
安卡

maybe because CGRectMake(50.0, 50.0, 0, 0) creates a CGRect with width = 0 and height = 0?

cheers,
anka

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文