現在很多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:]
的作用
情況一:[menu setTargetRect:CGRectMake(100, 100, 0, 0) inView:self.label]
此時菜單的座標原點是基於label自身
情況二:[menu setTargetRect:CGRectMake(100, 100, 0, 0) inView:self.view]
此時菜單的座標原點是基於屏幕左上角
大家對比兩種情況就知道,這個方法就是調整菜單的位置的。
總結
讓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、 實現各種自定義菜單選項對應的操作方法(刪除,賦值,粘貼等)