Подтвердить что ты не робот

Как я могу заменить UIMenuController своим собственным представлением при выборе текста?

Когда текст выбран, по умолчанию открывается UIMenuController с вырезанием/копированием/вставкой и т.д.

enter image description here

Я хотел бы заменить это своим собственным пользовательским представлением (похожим взглядом, но в два раза выше, чтобы у меня было два ряда кнопок/пользовательских представлений). Как я могу это сделать?

Я знаю, что нет простого способа. Я ожидаю, что если будет простое решение, это будет не очень элегантно. Код не может использовать какой-либо частный API.

Мне бы действительно не хотелось бы реализовывать собственное текстовое представление, переориентировать выбор текста и ввод и переопределять увеличительное представление, чтобы я мог написать свой собственный клон UIMenuController, если есть способ избежать его. Это очень важно для интерфейса приложения, что я могу заменить UIMenuController, поэтому, если нет другого ответа, я могу закончить это. Я буду ОЧЕНЬ благодарен, если кто-то может спасти мне приличный кусок времени и предложить другой, более простой способ сделать это!

4b9b3361

Ответ 1

Перед началом работы вы должны знать три важные вещи:

1) Вам нужно будет написать свой пользовательский вид контроллера меню, но я думаю, вы ожидали этого. Я знаю только коммерческую реализацию настраиваемого контроллера меню, но это не должно быть слишком сложно.

2) В UIResponder есть полезный метод, называемый -canPerformAction:withSender:. Подробнее об этом читайте в Справочник по классу UIResponder. Вы можете использовать этот метод, чтобы определить, поддерживает ли ваше текстовое представление конкретное стандартное действие (определенное в протоколе UIResponderStandardEditActions).
Это будет полезно при выборе элементов, которые будут отображаться в вашем настраиваемом контроллере меню. Например, пункт меню "Вставить" будет отображаться только в том случае, если панель пользователя содержит строку для вставки.

3) Вы можете определить, когда будет отображаться UIMenuController, прослушивая уведомление UIMenuControllerWillShowMenuNotification.

Теперь, когда вы все это знаете, я начну с этого:

1) Слушайте UIMenuControllerWillShowMenuNotification, когда текстовое представление является первым ответчиком

- (void)textViewDidBeginEditing:(UITextView *)textView {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuWillBeShown:) name:UIMenuControllerWillShowMenuNotification object:nil];
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillShowMenuNotification object:nil];
}

2) Покажите свой пользовательский контроллер меню вместо стандартного UIMenuController

- (void)menuWillBeShown:(NSNotification *)notification {
    CGRect menuFrame = [[UIMenuController sharedMenuController] menuFrame];
    [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO]; // Don't show the default menu controller

    CustomMenuController *controller = ...;
    controller.menuItems = ...;
    // additional stuff goes here

    [controller setTargetRectWithMenuFrame:menuFrame]; // menuFrame is in screen coordinates, so you might have to convert it to your menu presenting view/window/whatever

    [controller setMenuVisible:YES animated:YES];
}

Разное. 1) Вы можете использовать полноэкранный UIWindow для отображения своего пользовательского меню, чтобы он мог перекрывать строку состояния.

UIWindow *presentingWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
presentingWindow.windowLevel = UIWindowLevelStatusBar + 1;
presentingWindow.backgroundColor = [UIColor clearColor];

[presentingWindow addSubview:controller];
[presentingWindow makeKeyAndVisible];

Разное. 2). Для определения отображаемых пунктов меню вы можете использовать упомянутый -canPerformAction:withSender:

BOOL canPaste = [textView canPerformAction:@selector(paste:) withSender:nil];
BOOL canSelectAll = [textView canPerformAction:@selector(selectAll:) withSender:nil];

Разное. 3) Вам придется обрабатывать отклонение меню самостоятельно, используя UITapGestureRecognizer в окне представления или что-то в этом роде.

Это будет нелегко, но это выполнимо, и я надеюсь, что это сработает хорошо для вас. Удачи!

Update:
Сегодня на cocoacontrols.com появилась новая реализация меню, которую вы можете захотеть проверить: https://github.com/questbeat/QBPopupMenu

Обновление 2:
Как объяснено в этом ответе, вы можете получить кадр текстового просмотра выделенного текста с помощью -caretRectForPosition:.

Ответ 2

Я думаю, это может помочь вам https://github.com/cxa/UIMenuItem-CXAImageSupport

UIMenuItem использует UILabel для отображения своего названия, что означает, что мы можем swizzle -drawTextInRect: поддерживать изображение.

UIMenuItem + CXAImageSupport - это грязный хак, но в большинстве случаев он должен быть безопасным. Не содержит никакого частного API.

Создайте категорию вместо подкласса для UIMenuItem, получив большую гибкость. Да, эта категория также может быть применена к удивительному PSMenuItem!

enter image description here