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

时间:2013-11-15 13:05:24

标签: ios objective-c uimenucontroller

我正在开发一个支持在UITextView中编辑attributesText的应用程序。为了向用户提供格式化输入的工具,我使用inputAccessoryView来增强键盘的选项,如项目符号列表,编号列表,缩进,outdent,字体控件(粗体,下划线,增加字体大小,减小字体大小)等这太多了,无法放在inputAccessoryView上,所以我希望使用UIMenuController提供一种机制,为用户提供更多的空间,让他们知道自己的意图。

所以,我有一个带有'listAccessory'按钮的inputAccessoryView。按下它时,我想显示一个带有四个选项的UIMenuController(项目符号,数字,增加缩进,减少缩进)。但是当我显示这个菜单时,它还包括'select','selectAll'和'paste'。

我没有在我的视图中定义的任何这些方法(select:,selectAll:或paste:在UIResponderStandardEditActions非正式协议中定义)。我已经定义了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];
}

当我记录在此代码中调用的选择器时,我没有看到任何'select:','selectAll:'或'paste:'的请求,所以我相信UIMenuController代码正在测试这些方法直接调用canPerformSelector()对类。

由于我没有在我的viewController中实现这些函数(从UITableViewController派生),我只能相信UIMenuController正在查找响应者链并且看到最初启动键盘的响应者是UITextView,这就是DOES支持select,selectAll和paste。

所以我有几个问题:

1)是我对情况的理解吗?

2)如何强制不显示这些菜单项?我能以某种方式暂时打破响应者链而不解雇键盘吗?

1 个答案:

答案 0 :(得分:1)

很酷的问题。问题是您理解的。UITextView是您尝试调用菜单时的第一个响应者,因此它会使用SelectSelect All操作填充菜单

解决方案是子类UITextView并添加一个额外的属性,允许您暂时阻止这些项目。

我尝试了这个,它适用于UITextField作为我必须提供的东西但是没有理由相信它不适用于UITextView

轻轻地对你的观点进行细分。

@interface CharlieDevTextView : UITextView

@property BOOL blockActionMenu;

@end

并且

@implementation CharlieDevTextView

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

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

}

@end

然后在构建菜单时(假设您有一个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;
}

或者,请收听UIMenuControllerWillShowMenuNotificationUIMenuControllerDidHideMenuNotification,以便开启和关闭阻止功能。

并且可能使它稍微不那么难看创建委托而不是属性。您的视图控制器将是委托和谓词是否即将显示菜单或注意到菜单已被解除。

基本相同的效果,不同的模式。

@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