什麼是UIMenuController?
UIMenuController是UIKit裏面的控件
UIMenuController的作用在開發中彈出的菜單欄
後面介紹了菜單欄顯示中文的設置
有哪些控件是自帶UIMenuController菜單欄效果的呢?
- UITextField
- UITextView
- UIWebView
主要介紹兩種:
一種是控制器爲第一響應者
另一種是當前UI控件爲第一響應者 (把方法封裝在控件裏面)
具體看代碼,註釋裏我會詳細講解,如果實在不懂不妨動手敲一遍
-
@interface ViewController ()
-
@property (weak, nonatomic) IBOutlet UILabel *label;
-
@end
-
-
@implementation ViewController
-
-
- (void)viewDidLoad {
-
[super viewDidLoad];
-
-
//首先要允許label可以跟用戶交互
-
self.label.userInteractionEnabled = YES;
-
//給label添加一個敲擊手勢
-
[self.label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];
-
}
-
-
/** 點擊label觸發的方法 */
-
- (void)labelClick
-
{
-
//控制器不需要調用這個方法, 但是其他亂七八糟的UI控件就需要調用這個方法 \
-
因爲控制器默認是第一響應者
-
//[self becomeFirstResponder];
-
-
//顯示menu 從來沒有讓menu跟控制器有關係 , 因爲是第一響應者, 所以會調用第一響應者的方法
-
-
//不一定調用控制器的方法, 因爲現在控制器是第一響應者
-
-
-
-
// 獲得菜單
-
UIMenuController *menu = [UIMenuController sharedMenuController];
-
-
// 菜單最終顯示的位置
-
CGRect rect = CGRectMake(100, 100, 100, 100);
-
[menu setTargetRect:rect inView:self.label];
-
//爲什麼要設置2個參數 爲了通用 \
-
一個是矩形框, 一個是在哪個View上面
-
//傳了矩形框, 要告訴座標原點在哪, 座標原點就在view上\
-
以tagreView的左上角爲座標原點
-
// 蘋果設計2個參數 是因爲矩形框一旦修改 出現的位置在哪裏都是可以的
-
-
/*
-
targetRect:menuController指向的矩形框
-
targetView:targetRect以targetView的左上角爲座標原點
-
*/
-
-
// 顯示菜單
-
[menu setMenuVisible:YES animated:YES];
-
-
/*
-
得通過第一響應者,來告訴MenuController它內部應該顯示什麼內容
-
*/
-
}
-
-
#pragma mark - 第一響應者 + UIMenuController
-
/**
-
* 說明控制器可以成爲第一響應者
-
* 因爲控制器是因爲比較特殊的對象,它找控制器的方法,不找label的方法
-
*/
-
- (BOOL)canBecomeFirstResponder
-
{
-
return YES;
-
}
-
-
/**
-
* 通過這個方法告訴UIMenuController它內部應該顯示什麼內容
-
* 返回YES,就代表支持action這個操作
-
*/
-
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
-
{
-
//打印, 將一個方法轉換成字符串 你就會看到許多方法
-
NSLog(@"%@",NSStringFromSelector(action));
-
-
if (action == @selector(cut:)
-
|| action == @selector(copy:)
-
|| action == @selector(paste:)) {
-
return YES;
-
}
-
-
return NO;
-
}
-
-
//監聽事情需要對應的方法 冒號之後傳入的是UIMenuController
-
- (void)cut:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
-
-
- (void)copy:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
-
-
- (void)paste:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
上面只是簡單的介紹了UIMenuController的基本知識,下面正在帶你運用到開發中的知識,封裝一個自定義控件裏面實現,
附上大概效果:
上代碼,代碼有具體的註釋,還有具體的用法,所以認真閱讀代碼即可,就不附上demo了
-
#import "JHLabel.h"
-
-
@implementation JHLabel
-
-
/** 不管控件是通過xib stroyboard 還是純代碼 提供兩種初始化的操作都調用同一個方法 */
-
- (instancetype)initWithFrame:(CGRect)frame
-
{
-
if (self = [super initWithFrame:frame]) {
-
[self setupTap];
-
}
-
return self;
-
}
-
/** 不管控件是通過xib stroyboard 還是純代碼 提供兩種初始化的操作都調用同一個方法 */
-
- (void)awakeFromNib
-
{
-
[self setupTap];
-
}
-
/** 設置敲擊手勢 */
-
- (void)setupTap
-
{
-
-
self.text = @"author:會跳舞的獅子";
-
//已經在stroyboard設置了與用戶交互,也可以用純代碼設置
-
// self.userInteractionEnabled = YES;
-
-
//當前控件是label 所以是給label添加敲擊手勢
-
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];
-
-
}
-
/** 點擊label觸發的方法 */
-
- (void)labelClick
-
{
-
// 讓label成爲第一響應者 \
-
一定要寫這句話 因爲這句話纔是主動讓label成爲第一響應者
-
[self becomeFirstResponder];
-
-
// 獲得菜單
-
UIMenuController *menu = [UIMenuController sharedMenuController];
-
-
// 設置菜單內容 \
-
因爲menuItems是數組 官方沒有給出需要傳入什麼對象,但是以經驗可以判斷出需要傳入的是UIMenuItem對象 \
-
而且顯示是按順序的
-
menu.menuItems = @[
-
[[UIMenuItem alloc] initWithTitle:@"頂" action:@selector(ding:)],
-
[[UIMenuItem alloc] initWithTitle:@"回覆" action:@selector(reply:)],
-
[[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(warn:)]
-
];
-
-
// 菜單最終顯示的位置 \
-
有兩種方式: 一種是以自身的bounds 還有一種是以父控件的frame
-
[menu setTargetRect:self.bounds inView:self];
-
// [menu setTargetRect:self.frame inView:self.superview];
-
-
// 顯示菜單
-
[menu setMenuVisible:YES animated:YES];
-
}
-
-
#pragma mark - UIMenuController相關
-
/**
-
* 讓Label具備成爲第一響應者的資格
-
*/
-
- (BOOL)canBecomeFirstResponder
-
{
-
return YES;
-
}
-
-
/**
-
* 通過第一響應者的這個方法告訴UIMenuController可以顯示什麼內容
-
*/
-
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
-
{
-
if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持複製
-
|| (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切
-
|| action == @selector(paste:)
-
|| action == @selector(ding:)
-
|| action == @selector(reply:)
-
|| action == @selector(warn:)) return YES;
-
-
return NO;
-
}
-
-
#pragma mark - 監聽MenuItem的點擊事件
-
/** 剪切 */
-
- (void)cut:(UIMenuController *)menu
-
{
-
//UIPasteboard 是可以在應用程序與應用程序之間共享的 \
-
(應用程序:你的app就是一個應用程序 比如你的QQ消息可以剪切到百度查找一樣)
-
// 將label的文字存儲到粘貼板
-
[UIPasteboard generalPasteboard].string = self.text;
-
// 清空文字
-
self.text = nil;
-
}
-
/** 賦值 */
-
- (void)copy:(UIMenuController *)menu
-
{
-
// 將label的文字存儲到粘貼板
-
[UIPasteboard generalPasteboard].string = self.text;
-
}
-
/** 粘貼 */
-
- (void)paste:(UIMenuController *)menu
-
{
-
// 將粘貼板的文字賦值給label
-
self.text = [UIPasteboard generalPasteboard].string;
-
}
-
-
//如果方法不實現,是不會顯示出來的
-
- (void)ding:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
-
-
- (void)reply:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
-
-
- (void)warn:(UIMenuController *)menu
-
{
-
NSLog(@"%s %@", __func__, menu);
-
}
-
@end
上面的代碼,menu只顯示在label的上面 而一般菜單欄我們都是顯示在cell的中間, 下面的這幅圖詳細講解了顯示在cell的中間
-
/** 點擊cell的時候調用 */
-
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
-
{
-
// 取出cell
-
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
-
-
UIMenuController *menu = [UIMenuController sharedMenuController];
-
-
// 設置菜單內容
-
menu.menuItems = @[
-
[[UIMenuItem alloc] initWithTitle:@"頂" action:@selector(ding:)],
-
[[UIMenuItem alloc] initWithTitle:@"回覆" action:@selector(reply:)],
-
[[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(warn:)]
-
];
-
-
// 顯示位置
-
CGRect rect = CGRectMake(0, cell.height * 0.5, cell.width, 1);
-
[menu setTargetRect:rect inView:cell];
-
-
// 顯示出來
-
[menu setMenuVisible:YES animated:YES];
-
}
-
-
#pragma mark - 獲得當前選中的評論
-
- (JHComment *)selectedComment
-
{
-
// 獲得被選中的cell的行號
-
NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
-
NSInteger row = indexPath.row;
-
-
// 獲得評論數據
-
NSArray *comments = self.shortComments;
-
if (indexPath.section == 0 && self.longComments.count) {
-
comments = self.longComments;
-
}
-
-
return comments[row];
-
}
-
-
#pragma mark - UIMenuController處理
-
- (BOOL)canBecomeFirstResponder
-
{
-
return YES;
-
}
-
-
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
-
{
-
if (!self.isFirstResponder) { // 文本框彈出鍵盤, 文本框纔是第一響應者
-
if (action == @selector(ding:)
-
|| action == @selector(reply:)
-
|| action == @selector(warn:)) return NO;
-
//如果是文本框,那麼這些顯示都不返回
-
}
-
-
return [super canPerformAction:action withSender:sender];
-
}
-
-
- (void)ding:(UIMenuController *)menu
-
{
-
NSLog(@"ding - %@ %@",
-
self.selectedComment.user.username,
-
self.selectedComment.content);
-
}
-
-
- (void)reply:(UIMenuController *)menu
-
{
-
NSLog(@"reply - %@ %@",
-
self.selectedComment.user.username,
-
self.selectedComment.content);
-
}
-
-
- (void)warn:(UIMenuController *)menu
-
{
-
NSLog(@"warn - %@ %@",
-
self.selectedComment.user.username,
-
self.selectedComment.content);
-
}
-
-
#注: 這裏的self.selectedComent
-
# (點語法 要麼調用set方法要麼調用get方法, 這裏直接用點語法是沒有提示的,我已經進行了聲明)
-
#/** 寫方法聲明的目的是爲了使用點語法提示 */
-
#- (JHComment *)selectedComment;