美文网首页iOS系统框架视图控件
简介UIMenuController的使用

简介UIMenuController的使用

作者: BrightFuture | 来源:发表于2016-09-10 15:58 被阅读357次
    图中黑色的菜单就是UIMenuController

    默认已经支持UIMenuController的控件:

    • UITextField
    • UITextView
    • UIWebView

    让其他控件也支持UIMenuController(比如UILabel)

    • 自定义UILabel,让其成为第一响应者,并添加点击手势
      - (void)setUp { 
        // 1.设置label可以交互 
        self.userInteractionEnabled = YES;  
        // 2.添加点击手势 
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)]];
      }
      - (void)click { 
        // 3.设置label为第一响应者,只有成为响应者才能够将MenuController显示在其上面 
        [self becomeFirstResponder]; 
        // 4.初始化UIMenuController 
        UIMenuController *menuController = [UIMenuController sharedMenuController];  
        // 5.设置UIMenuController显示的位置 
        // targetRect : 将要显示所在label的frame; 
        // view : targetRect所在的坐标系参照物(父view或self)
        [menuController setTargetRect:self.frame inView:self.superview];
        // [menuController setTargetRect:self.bounds inView:self];作用同上  
        // 6.显示UIMenuController 
        [menuController setMenuVisible:YES animated:YES];
      }
    
    • 重写2个方法
      /** * 让label有资格成为第一响应者 */
      - (BOOL)canBecomeFirstResponder{ 
        return YES;
      }
      /** * label能执行哪些操作(比如copy, paste等等) 
        * @return YES:支持这种操作 
        */
      - (BOOL)canPerformAction:(SEL)action withSender:(id)sender{ 
        if (action == @selector(cut:) || action == @selector(copy:) || action == @selector(paste:)) return YES; return NO;
      }
    
    • 实现各种操作方法
      - (void)cut:(UIMenuController *)menu { 
        // 将自己的文字复制到粘贴板 
        [self copy:menu]; 
        // 清空文字 
        self.text = nil;
      }
      - (void)copy:(UIMenuController *)menu{ 
        // 将自己的文字复制到粘贴板 
        UIPasteboard *board = [UIPasteboard generalPasteboard];
        board.string = self.text;
      }
      - (void)paste:(UIMenuController *)menu{ 
        // 将粘贴板的文字 复制 到自己身上 
        UIPasteboard *board = [UIPasteboard generalPasteboard]; 
        self.text = board.string;
      }
    

    自定义UIMenuController内部的Item(以cell为例)

    • 点击cell显示/隐藏MenuController
    • 由于手动添加的MenuItem默认触发控制器中的方法,所以将MenuController的显示/隐藏,添加MenuItem写到控制器中(上面Label的例子是让控件支持系统自带的一些MenuItem,现在讲的是如何支持自己定义的一些MenuItem)
      - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
        // 点击cell弹出UIMenuController 
        // 1.如果menuController已经在显示,就隐藏他
        // 注意,如果有一个cell正在显示menuController,这时再点击另外一个cell,上一个cell的menuController会消失,当前点击cell会显示,这是因为上一个cell不再是第一响应者了,menuController会自动释放 
        UIMenuController *menuController = [UIMenuController sharedMenuController]; 
        if (menuController.isMenuVisible) { 
          [menuController setMenuVisible:NO animated:YES];  
        }else { 
          // 2.显示MenuController 
          // 先设置cell为第一响应者,同时不要忘记在cell中重写canBecomeFirstResponder和canPerformAction:withSender: 
          JCMTopicCommentCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
          [cell becomeFirstResponder]; 
          // 添加menuItem 
          UIMenuItem *item01 = [[UIMenuItem alloc]initWithTitle:@"顶" action:@selector(ding:)]; 
          UIMenuItem *item02 = [[UIMenuItem alloc]initWithTitle:@"回复" action:@selector(response:)]; 
          UIMenuItem *item03 = [[UIMenuItem alloc]initWithTitle:@"举报" action:@selector(report:)]; 
          menuController.menuItems = @[item01,item02,item03]; 
          // 设置menuControoler显示位置 
           CGRect showRect = CGRectMake(cell.x, cell.y + cell.height/2, cell.width, cell.height); 
           [menuController setTargetRect:showRect inView:cell.superview]; 
          // 显示menuController [menuController setMenuVisible:YES animated:YES];  
        }
    }
    
    • 处理方法的实现
      #pragma mark - MenuController处理
      // MenuController手动添加的item的方法实现必须放在controller中
      - (void)ding:(UIMenuController *)menu { 
          NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
          NSLog(@"%s %@", __func__, [self commentInIndexPath:indexPath].content);
      }
      - (void)response:(UIMenuController *)menu { 
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
        NSLog(@"%s %@", __func__, [self commentInIndexPath:indexPath].content);
      }
      - (void)report:(UIMenuController *)menu { 
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
        NSLog(@"%s %@", __func__, [self commentInIndexPath:indexPath].content);
      }
    
    • cell中实现两个方法
      // 是否可以成为第一响应者
      - (BOOL)canBecomeFirstResponder { 
        return YES;
      }
      // 是否可以执行哪些方法
      - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 
        return NO;
     }```

    相关文章

      网友评论

      • 有偶像包袱的程序狗:请问自定义item,怎么传参数啊?
        BrightFuture:@有偶像包袱的程序狗 // 添加menuItem
        UIMenuItem *item01 = [[UIMenuItem alloc]initWithTitle:@"顶" action:@selector(ding:)];
        UIMenuItem *item02 = [[UIMenuItem alloc]initWithTitle:@"回复" action:@selector(response:)];
        UIMenuItem *item03 = [[UIMenuItem alloc]initWithTitle:@"举报" action:@selector(report:)];
        menuController.menuItems = @[item01,item02,item03];
      • feng_dev:那如果我cell里面有个button 想要实现menu 呢,就像微信朋友圈一样
        feng_dev:@BrightFuture 你的文章里面说的是如果自定义label是为了让label有系统的menuitem的方法,如果要自定义item的话,是不是必须要把添加item写在控制器里面啊
        feng_dev:@BrightFuture 感谢回复,如果是继承UIbutton 写一个自定义button的话,那这些代码都是写在button里面的,怎么做一些和ID有关的操作啊,你建议写在控制器还是button里面
        BrightFuture:@Developer_峰 我尝试了一下,发现button必须becomeFirstResponder,而且button要自定义,里面要实现canBecomeFirstResponder,这两个条件都满足的情况下UIMenuController才会显示,可以通过打印UIMenuController的menuFrame属性来测试。(PS:发现即使不重写canPerformAction: withSender:这个方法,也只会出现自己添加的menuItem,可能它默认就是返回NO吧- -)
      • feng_dev:由于手动添加的MenuItem默认触发控制器中的方法,所以将MenuController的显示/隐藏,添加MenuItem写到控制器中(上面Label的例子是让控件支持系统自带的一些MenuItem,现在讲的是如何支持自己定义的一些MenuItem)
        这句话太重要了 感谢大神

      本文标题:简介UIMenuController的使用

      本文链接:https://www.haomeiwen.com/subject/auiyettx.html