为UILabel添加弹出UIMenuController功能


现在很多App,类似于新浪博客、QQ空间等都支持按住文字,然后弹出一个菜单让你可以选择复制、粘帖等功能。如下图所示

我们都知道这是通过UIMenuController来实现的,而文字的显示一般是通过UILabel来实现的,但是默认情况下UILabel并不支持UIMenuController。不过我们可以给它添加这么一个功能,下面看看具体如何做的。

UIMenuController须知
  • 默认情况下, 有以下控件已经支持UIMenuController
    • UITextField
    • UITextView
    • UIWebView

如果想让UILabel也支持上图所示的UIMenuController,就必须做如下操作:

  • 自定义UILabel
  • 重写2个方法
  • 自定义menuitem

新建一个项目,然后再新建两个类,继承自UILabel,实现自定义UILabel支持 UIMenuController

具体实现代码如下:
WSLabel.m  
==============

#import "WSLabel.h"

@implementation WSLabel

- (void)awakeFromNib
{
    [self setup];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setup];
    }
    return self;
}

/**
 * 让label可以响应用户操作
 */
- (void)setup
{
    self.userInteractionEnabled = YES;
}


//PS:下面两个方法必须在自定义Label里面实现

/**
 * 让label有资格成为第一响应者
 */
- (BOOL)canBecomeFirstResponder
{
    return YES;
}

/**
 * label能执行哪些操作(比如copy, paste等等)
 * @return  YES:支持这种操作
*  由于这里需要实现自定义的中文菜单,而不是使用默认的,所以这里选择NO
 */
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    return NO;
}
@end

在Main.storyboard上面放一个UIlabel,然后拖到viewcontroller里面。

ViewController.m  
=====================
//注意这里选择的是自定义的WSLabel,而不是系统的UILabel
@property (weak, nonatomic) IBOutlet WSLabel *label;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

//给label添加手势,点击触发labelClick方法
    [self.label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];
}

- (void)labelClick
{
    // 1.label要成为第一响应者(作用是:告诉UIMenuController支持哪些操作, 这些操作如何处理)
    [self.label becomeFirstResponder];

    // 2.显示MenuController
    UIMenuController *menu = [UIMenuController sharedMenuController];

/*    
 添加自定义的MenuItem
注意:
不要写系统自带的copy,paste,delete,不然会生成相应的菜单
*/
    UIMenuItem *ding = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(copys:)];
    UIMenuItem *replay = [[UIMenuItem alloc] initWithTitle:@"粘帖" action:@selector(pastes:)];
    UIMenuItem *report = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deletes:)];
    menu.menuItems = @[ding, replay, report];

/*
 targetRect: MenuController的小箭头需要指向位置
 inView: targetRect会以inView后面的控件所在位置(这里是label所在位置)的左上角为自己的坐标原点
上面两个综合起来就确定了菜单所在位置
先用inView,确定坐标原点,再用targetRect相对该坐标原点进行偏移即可以得到菜单所在位置,下面我会具体演示
*/
    [menu setTargetRect:self.label.bounds inView:self.label];

    [menu setMenuVisible:YES animated:YES];
}


//如果是自定义menuitem,那么该Menuitem对应的方法就必须放在label所在的控制器去实现,而不是自身
- (void)deletes:(UIMenuController *)menu
{
    // 清空文字
    self.label.text = nil;
}

- (void)copys:(UIMenuController *)menu
{
    // 将自己的文字复制到粘贴板
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    board.string = self.label.text;
}

- (void)pastes:(UIMenuController *)menu
{
    // 将粘贴板的文字 复制 到自己身上
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    self.label.text = board.string;
}@end
最后实现功能如下:

下面我们再看看代码[menu setTargetRect: inView:]的作用


此时菜单的坐标原点是基于label自身


此时菜单的坐标原点是基于屏幕左上角

大家对比两种情况就知道,这个方法就是调整菜单的位置的。


总结

让UILabel支持自定义的菜单大体分为如下五步:

1、自定义UILabel

2、重写2个方法 

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

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

    return NO;
}

3、 让label成为第一响应者[self.label becomeFirstResponder]

4、 显示UIMenuControllersetTargetRect: inView:

5、 添加自定义的菜单选项

6、 实现各种自定义菜单选项对应的操作方法(删除,赋值,粘贴等)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值