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];
Ошибок или исключений нет, но контроллер меню просто не отображается.
Ответы
Ответ 1
Вам нужно сделать три вещи:
Ответ 2
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.
Ответ 3
В ответе упоминаются три вещи, но чтобы быть разборчивыми, есть шесть:
- Обработчик меню должен быть UIView. Если это не так,
-becomeFirstResponder
терпит неудачу.
- Обработчик меню должен иметь
userInteractionEnabled = YES
- Обработчик меню должен находиться в иерархии представления, а его свойство
-window
должно быть таким же, как и окно для представления в аргументе inView:
.
- Вам нужно реализовать
-canBecomeFirstResponder
и вернуть YES
.
- Вам нужно вызвать
[handler becomeFirstResponder]
, до того, как вызывается [menu setTargetRect:inView:]
, или последний не будет выполнен.
- Вам нужно позвонить
[menu setTargetRect:inView]
(по крайней мере один раз) и [menu setMenuVisible:animated:]
.
В частности, пункты 1-3 выше меня. Мне нужен пользовательский класс обработчика меню, который сначала был UIResponder
, из-за чего -becomeFirstResponder
возвращал NO
; то это был UIView
, который потерпел неудачу, затем я попытался сделать его UIButton
, который работал, но только потому, что userInteractionEnabled
по умолчанию имеет значение YES
для кнопок и NO
для UIView
s.
Ответ 4
Ниже приведен полный рабочий пример с комментариями...
Просмотр файла заголовка подкласса
#import <Foundation/Foundation.h>
@interface MenuControllerSupportingView : UIView
{
}
@end
Просмотр исходного файла подкласса
#import "MenuControllerSupportingView.h"
@implementation MenuControllerSupportingView
//It 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 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 mandatory
[vu becomeFirstResponder];
//It 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 write return YES alone in canPerformAction, вы увидите все стандартные элементы меню, такие как символ камеры, вырезать, скопировать и т.д.
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return YES;
}
Если вы хотите показать что-то вроде камеры, тогда
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if([email protected](_insertImage:))
return YES;
else
return NO;
}
если u хочет узнать обо всех действиях, то
посетите ссылку
Ответ 5
На всякий случай, если кто-то имеет эту проблему специально (и случайно) с iOS6: вы можете посмотреть this SO, связанный с включением Speak Selection на устройстве (Настройки → Общие → Доступность → Выбор речи: Вкл.). Небольшое число моих пользователей не смогли увидеть пользовательский UIMenuItems
, и это стало причиной.
Ответ 6
В 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
}
}
}
Ответ 7
возможно, потому что CGRectMake(50.0, 50.0, 0, 0)
создает CGRect
с width = 0
и height = 0
?
веселит,
Anka