Не удается получить UIMenuController для отображения пользовательских элементов
Итак, я не уверен, что делаю что-то не так, но у меня есть UIViewController, на котором есть UICollectionView. В UIViewController's viewDidLoad
метод, я делаю следующее, он не добавляет какие-либо пользовательские пункты меню во всплывающее окно, которое появляется.
UIMenuItem *removeItem = [[UIMenuItem alloc] initWithTitle:@"Remove" action:@selector(handleRemoveItem:)];
UIMenuItem *duplicateItem = [[UIMenuItem alloc] initWithTitle:@"Duplicate" action:@selector(handleDuplicateItem:)];
[[UIMenuController sharedMenuController] setMenuItems:@[removeItem, duplicateItem]];
[removeItem release];
[duplicateItem release];
Я установил collectionView:shouldShowMenuForItemAtIndexPath:
и collectionView:canPerformAction:forItemAtIndexPath:withSender:
возвращать YES
при любых обстоятельствах, но не смотря ни на что, будут отображаться только "Вырезать", "Копировать" и "Вставить".
Разве я не реализовал это полностью, или я не сделал это правильно?
PS - Я просмотрел как можно больше примеров в Google и не нашел ничего, что могло бы помочь.
3 ответа
Ты прав. Невозможно настроить меню, которое появляется при длительном нажатии на ячейку табличного представления или ячейку представления коллекции.
Я обсуждаю проблему в моей книге:
http://www.apeth.com/iOSBook/ch21.html
Как я уже сказал, Копировать, Вырезать и Вставить - это единственный выбор, который вы можете иметь. Вам нужно будет заставить меню исходить из чего-то другого, если вы хотите настроить его.
РЕДАКТИРОВАТЬ: В версии моей книги для iOS 7, я демонстрирую способ сделать это. То же самое касается ячеек табличного представления и ячеек коллекционного представления, поэтому я начну с решения для ячеек табличного представления. Хитрость заключается в том, что вы должны реализовать метод действия в подклассе ячейки. Например, если ваш селектор пользовательских действий abbrev:
, вы должны создать подкласс ячейки и реализовать abbrev:
:
Это единственная сложная часть. Затем, вернувшись в свой класс контроллера, вы делаете для abbrev:
именно то, что вы сделали бы для любого меню. В shouldShowMenuForRowAtIndexPath:
добавьте его в пользовательское меню. Затем реализовать canPerformAction:
а также performAction:
как и следовало ожидать (прокрутите до конца):
Вот параллельная реализация для ячеек представления коллекции: подкласс ячейки:
И контроллер (прокрутите до конца):
Эти подходы также переведены на Swift (не без каких-либо трудностей) в издании iOS 8 моей книги.
Мне удалось реализовать пользовательские меню на UICollectionViewCell, следуя инструкциям по этой ссылке ( /questions/33148644/kopirovat-vyinosku-v-uicollectionview/33148646#33148646) с некоторой импровизацией.
В моем UICollectionViewController я реализовал пользовательские пункты меню, добавив их в контроллер меню, как в ссылке.
Затем я реализовал следующее в UICollectionViewController:
- (BOOL)collectionView:(UICollectionView *)cv canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
return NO;
}
- (BOOL)collectionView:(UICollectionView *)cv shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)collectionView:(UICollectionView *)cv performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
NSLog(@"perform action:%@", NSStringFromSelector(action));
}
В моем UICollectionViewCell я реализовал примерно следующее:
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(onCustom1:)) {
return YES;
}
if (action == @selector(onCustom2:)) {
return YES;
}
return NO;
}
Эти действия должны быть такими же, как реализованные в контроллере коллекции.
Если кто-то хочет включить функции копирования или вставки, добавьте их в canPerformAction: и затем измените collectionView::canPerformAction: для возврата YES.
Возможно, это не лучший способ сделать это, но сработало для меня.
Шаг 1. Создание пунктов меню
UIMenuItem* miCustom1 = [[UIMenuItem alloc] initWithTitle:@"Custom 1" action:@selector(onCustom1:)];
UIMenuItem* miCustom2 = [[UIMenuItem alloc] initWithTitle: @"Custom 2" action:@selector(onCustom2:)];
Шаг 2: Создать MenuController
UIMenuController* mc = [UIMenuController sharedMenuController];
Шаг 3: Добавить элементы в контроллер меню
mc.menuItems = [NSArray arrayWithObjects: miCustom1, miCustom2, nil];
Шаг 4. Создание методов действий для элементов
- (void) onCustom1: (UIMenuController*) sender
{
}
- (void) onCustom2: (UIMenuController*) sender
{
}
Шаг 5: опционально установить FirstResponder для действий
- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
if ( action == @selector( onCustom1: ) )
{
return YES; // logic here for context menu show/hide
}
if ( action == @selector( onCustom2: ) )
{
return NO; // logic here for context menu show/hide
}
if ( action == @selector( copy: ) )
{
// turn off copy: if you like:
return NO;
}
return [super canPerformAction: action withSender: sender];
}
Шаг 6: Наконец покажите свой MenuController на некоторых кнопках
UIMenuController* mc = [UIMenuController sharedMenuController];
CGRect bounds = sender.view.bounds;
[mc setTargetRect: sender.view.frame inView:sender.view.superview];
[mc setMenuVisible:YES animated: YES];