iOS-UIMenuController的使用


第一次使用UIMenuController,遇见一些问题,记录如下。

概念

UIMenuController即菜单控制器,是一个单例对象,用来复制,粘贴,删除等内容的操作。

使用步骤

通过下面三部完成UIMenuController的使用,缺一不可

  • 通过[UIMenuController sharedMenuController]来获取实例对象;
  • 通过 - (void)setTargetRect:(CGRect)targetRect inView:(UIView *)targetView设置菜单的显示位置,例如设置targetRect为下图的红色区域,那么菜单会显示在targetRect上方中间位置,如果上方中间位置在屏幕上不能够显示,那么会显示在下方中间位置。如果targetRect的宽度高度设置为零,那么会在一个点显示。(菜单会根据设置的区域自动调整位置,以便能全部显示出来);
  • 通过menuVisible属性设置为YES(或者setMenuVisible:animated:方法)令菜单显示出来。

使用菜单

假设点击控制器的view显示菜单,那么在控制的touchesBegan方法中按照上面说的三步设置UIMenuController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:CGRectMake(100, 300, 200, 20) inView:self.view];
    menu.menuVisible = YES;
}

此时我们运行程序,点击控制的view并没有弹出菜单,原因是:

1.控制器或者UIView能够成为first responder ,需要实现下面方法

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

2.在显示菜单时需要设置为first responder ,在touchesBegan中添加[self becomeFirstResponder];

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self becomeFirstResponder]; //设置为第一响应者 
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:CGRectMake(100, 300, 200, 20) inView:self.view];
    menu.menuVisible = YES;
}

3.并且需要实现UIResponder的canPerformAction:withSender:方法,该方法与编辑菜单相关,与返回YES的方法关联的菜单将显示出来。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(paste:))
    {
        return YES;
    } else if (action == @selector(cut:))
    {
        return YES;
    }
    else{
        return NO;
    }
}

其中paste:cut:方法都定义在UIResponderStandardEditActions协议,都是与菜单相关的。
由于只有paste:cut:方法能够响应,因此只显示cut和paste两个菜单,显示效果如下

如果直接返回YES,那么所有菜单都会显示,如下图。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
     return YES;
}

说明:如果canPerformAction:withSender: 的first responder没有处理事件,会顺着响应链向上抛。

使用自定义菜单

可以通过UIMenuItem来自定义菜单,需要设置菜单的显示内容以及点击菜单的后的处理方法。然后将自定义的UIMenuItem添加到UIMenuController的menuItems(一个数组)属性中。其它使用过程与上面讲解的使用菜单的过程一样。 具体使用见下面例子,

添加自定义菜单

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self becomeFirstResponder]; //成为第一响应者 
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:CGRectMake(100, 300, 200, 20) inView:self.view];
  // 定义两个菜单a和b
    UIMenuItem *a = [[UIMenuItem alloc] initWithTitle:@"a"
                        action:@selector(aAction)];
    UIMenuItem *b = [[UIMenuItem alloc] initWithTitle:@"b"
                             action:@selector(bAction)];
 // 自定义菜单添加到菜单栏中
    menu.menuItems = @[like,writeBack,report];
    menu.menuVisible = YES;
}

实现aActionbAction方法

- (void)aAction{
    NSLog(@"--aAction--")
}

- (void)bAction{
    NSLog(@"--bAction--")
}

控制器或者UIView能够成为first responder

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

实现canPerformAction:withSender:方法

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    // 显示一个系统的paste以及自定义的a,b菜单
    if (action == @selector(paste:) || 
    action == @selector(aAction) ||
    action == @selector(bAction))
    {
        return YES;
    } 
    else{
        return NO;
    }
}

运行程序,显效果如下

说明:系统的菜单会显示在自定义菜单之前。

其它说明

如下图红色箭头所指所示,菜单箭头指针默认向下,可以通过设置arrowDirection属性改变其方向,支持上下左右四个方法。

箭头指针最下面的点即- (void)setTargetRect:(CGRect)targetRect inView:(UIView *)targetView方法中targetRect说设置的位置,具体指向的点见使用步骤说解释。

参考资料

apple官方文档
关于UIMenuController的用法例子

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容