简体   繁体   English

在显示附加到inputAccessoryView的UIMenuController中隐藏'select','selectAll','paste'?

[英]Hiding 'select', 'selectAll', 'paste' in a UIMenuController displayed attached to a inputAccessoryView?

I am developing an app that supports editing attributedText in a UITextView. 我正在开发一个支持在UITextView中编辑attributesText的应用程序。 To provide the tools to the user for formatting their input, I am using an inputAccessoryView to augment the keyboard with options like bullet list, numbered list, indent, outdent, font controls (bold, underline, increase fontsize, decrease font size), etc. This is too much to fit on the inputAccessoryView so I am looking to use the UIMenuController to provide a mechanism to provide more space for the user to make their intentions known. 为了向用户提供格式化输入的工具,我使用inputAccessoryView来增强键盘的选项,如项目符号列表,编号列表,缩进,outdent,字体控件(粗体,下划线,增加字体大小,减小字体大小)等这太多了,无法放在inputAccessoryView上,所以我希望使用UIMenuController提供一种机制,为用户提供更多空间让他们知道他们的意图。

So, I have a inputAccessoryView with a 'listAccessory' button. 所以,我有一个带有'listAccessory'按钮的inputAccessoryView。 When it is pressed, I wanted to show a UIMenuController with four options (bullet, number, increase indent, decrease indent). 按下它时,我想显示一个带有四个选项的UIMenuController(项目符号,数字,增加缩进,减少缩进)。 But when I show this menu, it ALSO includes 'select', 'selectAll' and 'paste'. 但是当我显示这个菜单时,它还包括'select','selectAll'和'paste'。

I do not have any of these methods (select:, selectAll:, or paste: as defined in the UIResponderStandardEditActions informal protocol) defined in my view. 我没有在我的视图中定义的任何这些方法(select:,selectAll:或paste:在UIResponderStandardEditActions非正式协议中定义)。 I have defined canPerformAction:withSender: and only respond with 'YES' for my selectors. 我已经定义了canPerformAction:withSender:并且只对我的选择器响应'YES'。

- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender
{
    DDLogInfo(@"canPerformAction: %@", NSStringFromSelector(selector));

    if (selector == @selector(formatAsBulletList:)) return YES;
    if (selector == @selector(formatAsNumberedList:)) return YES;
    if (selector == @selector(formatIncreaseIndent:)) return YES;
    if (selector == @selector(formatDecreaseIndent:)) return YES;

    return NO; // return [super canPerformAction:selector withSender:sender];
}

When I log the selectors being called in this code, I don't see any request for 'select:', 'selectAll:', or 'paste:', so I believe that the UIMenuController code is testing for those methods with direct calls to canPerformSelector() against the class. 当我记录在这段代码中调用的选择器时,我没有看到任何'select:','selectAll:'或'paste:'的请求,所以我相信UIMenuController代码正在测试那些直接调用的方法toCerformSelector()对类。

Since I don't implement those functions in my viewController (derived from UITableViewController), I can only believe surmise that the UIMenuController is looking up the responder chain and seeing that the responder that initiatated the keyboard initially is a UITextView, which DOES support select, selectAll, and paste. 由于我没有在我的viewController中实现这些函数(从UITableViewController派生),我只能相信UIMenuController正在查找响应者链并且看到最初启动键盘的响应者是UITextView,它支持select, selectAll,并粘贴。

So I have a couple of questions: 所以我有几个问题:

1) is my understanding of the situation right? 1)是我对情况的理解吗?

2) how do I force those menu items to not appear? 2)如何强制不显示这些菜单项? Can I somehow temporarily break the responder chain without dismissing the keyboard? 我能以某种方式暂时打破响应者链而不解雇键盘吗?

Cool question. 很酷的问题。 The problem is as you understand it .The UITextView IS the first responder when you try to invoke your menu so it populates the menu with the Select and Select All actions 问题就在于你理解它。当你尝试调用菜单时, UITextView是第一个响应者,因此它使用SelectSelect All操作填充菜单

A solution is to subclass UITextView and add an extra property which allows you to block the items briefly. 一个解决方案是子类UITextView并添加一个额外的属性,允许您简单地阻止项目。

I tried this and it works on UITextField as its what i had to hand but theres no reason to believe it won't work on UITextView 我尝试了这个,它可以在UITextField因为它是我必须提供的但是没有理由相信它不适用于UITextView

Subclass your view lightly. 轻轻地对您的视图进行子类化。

@interface CharlieDevTextView : UITextView

@property BOOL blockActionMenu;

@end

And

@implementation CharlieDevTextView

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {

    if (self.blockActionMenu) {
        return NO;
    }
    return [super canPerformAction:action withSender:sender];

}

@end

then when you construct your menu (assuming you have an IBOutlet to the textview) 然后当你构建菜单时(假设你有一个IBOutlet到textview)

-(void)yellowMellow:(id)sender {

}


-(void)createMenuForButton:(UIButton *)sender
{
    UIMenuItem *newInstanceItem = [[UIMenuItem alloc] initWithTitle:@"Woot" action:@selector(yellowMellow:)];

    [UIMenuController sharedMenuController].menuItems = @[newInstanceItem];

    CGPoint apoint = sender.center;

    self.charlieTextView.blockActionMenu = YES;

    [[UIMenuController sharedMenuController] setTargetRect:CGRectMake(apoint.x,apoint.y, 0, 0) inView:sender.superview];

    [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];

    self.charlieTextView.blockActionMenu = NO;
}

Alternatively listen to the UIMenuControllerWillShowMenuNotification and UIMenuControllerDidHideMenuNotification for switching blocking on and off. 或者,也可以通过UIMenuControllerWillShowMenuNotificationUIMenuControllerDidHideMenuNotification来切换阻止打开和关闭。

and possibly to make it slightly less ugly create a delegate rather than a property. 并且可能使它稍微不那么难看创建一个委托而不是一个属性。 Your view controller will be the delegate and predicate on whether it is about to show the menu or noticed that the menu has been dismissed. 您的视图控制器将是委托和谓词是否即将显示菜单或注意到菜单已被解除。

Essentially same effect , different pattern. 基本相同的效果,不同的模式。

@protocol CharlieTextViewMenuDelegate <NSObject>

-(BOOL)shouldBlockMenu;

@end

@interface CharlieTextView : UITextView

@property (nonatomic,weak) id< CharlieTextViewMenuDelegate> menuDelegate;

@end

@implementation CharlieDevTextView

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {

    if ([self.menuDelegate shouldBlockMenu]) {
        return NO;
    }
    return [super canPerformAction:action withSender:sender];

}

@end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM