UIMenuController не отображается - PullRequest
57 голосов
/ 24 июня 2010

Я пытаюсь создать пользовательский 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];

Нет ошибок или исключений, но контроллер меню просто не появляется.

Ответы [ 7 ]

155 голосов
/ 09 сентября 2010

Вам нужно сделать три вещи:

  1. Вам необходимо вызвать -becomeFirstResponder на контроллере представления или просмотра.
  2. Ваш контроллер представления или представления должен реализовать -canBecomeFirstResponder (возвращая YES).
  3. Опционально, ваш контроллер представления или представления может реализовать -canPerformAction:action withSender:sender для отображения / скрытия пунктов меню на индивидуальной основе.
18 голосов
/ 24 мая 2014

Ответ упоминает три вещи, но чтобы быть разборчивыми, есть шесть:

  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 для кнопок и NO для UIView с.

15 голосов
/ 27 декабря 2010

UIMenuController отображается в любом представлении, только если представление является первым респондентом, а метод

- (BOOL)canPerformAction возвращает YES

Следовательно, если ваш контроллер меню должен отображаться на кнопкенажмите, первая строка в действии кнопки должна быть [self becomeFirstResponder].ПРИМЕЧАНИЕ: здесь self - это представление, которое будет представлять меню.

Если ваши меню должны отображаться при жесте длинного нажатия, добавьте longPressGesture в UIView и в событие longpress перед записью

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

запись [self becomeFirstResponder];

Затем выполните шаги, упомянутые OZ.

5 голосов
/ 09 августа 2013

Ниже приведен рабочий пример с полным комментарием ...

Просмотр заголовочного файла подкласса

#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, если вы пишете, верните YES отдельно в canPerformAction , вы увидите все стандартные элементы меню, такие как символ камеры, вырезать, скопировать и т. Д.

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

}

если вы хотите знать обо всех действиях, тогда

посетите ссылку

2 голосов
/ 25 декабря 2012

На всякий случай, если у кого-то возникла эта проблема специально (и случайно) с iOS6: вы можете посмотреть этот SO , связанный с включением Speak Selection на устройстве (Настройки -> Общие -> Специальные возможности)-> Speak Selection: On).Небольшое количество моих пользователей не смогли увидеть пользовательский UIMenuItems, и это было причиной.

1 голос
/ 14 марта 2017

В Swift 3.0 -

В моем случае я хотел, чтобы VC предварительно выделил текст в TextView и отобразил пользовательское меню, чтобы пользователь мог выполнить выбор. Как упомянуто Kalle , очень важен порядок, особенно последний setMenuVisible.

В ВК, viewDidLoad:

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

В ВК, когда пользователь нажимает кнопку:

@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
    }
  }
}
0 голосов
/ 24 июня 2010

возможно, потому что CGRectMake(50.0, 50.0, 0, 0) создает CGRect с width = 0 и height = 0?

веселит, Анка

...