【问题标题】:Hiding 'select', 'selectAll', 'paste' in a UIMenuController displayed attached to a inputAccessoryView?在附加到 inputAccessoryView 的 UIMenuController 中隐藏“select”、“selectAll”、“paste”?
【发布时间】:2013-11-15 13:05:23
【问题描述】:

我正在开发一个支持在 UITextView 中编辑属性文本的应用程序。为了向用户提供格式化输入的工具,我使用 inputAccessoryView 来增加键盘的选项,如项目符号列表、编号列表、缩进、缩进、字体控件(粗体、下划线、增加字体大小、减小字体大小)等. 这对于 inputAccessoryView 来说太多了,所以我希望使用 UIMenuController 来提供一种机制,为用户提供更多空间来表达他们的意图。

所以,我有一个带有“listAccessory”按钮的 inputAccessoryView。当它被按下时,我想显示一个带有四个选项(项目符号、数字、增加缩进、减少缩进)的 UIMenuController。但是当我显示这个菜单时,它还包括“选择”、“全选”和“粘贴”。

我的视图中没有定义任何这些方法(如 UIResponderStandardEditActions 非正式协议中定义的 select:、selectAll: 或 paste:)。我已经定义了 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,它确实支持全选、全选、粘贴。

所以我有几个问题:

1) 我对情况的理解正确吗?

2) 如何强制不显示这些菜单项?我可以在不关闭键盘的情况下以某种方式暂时中断响应者链吗?

【问题讨论】:

    标签: ios objective-c uimenucontroller


    【解决方案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)

    -(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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 2018-01-27
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多