UIMenuController——顏婧

什麼是UIMenuController?

UIMenuController是UIKit裏面的控件

UIMenuController的作用在開發中彈出的菜單欄

後面介紹了菜單欄顯示中文的設置


有哪些控件是自帶UIMenuController菜單欄效果的呢?

  • UITextField
  • UITextView
  • UIWebView

主要介紹兩種:

一種是控制器爲第一響應者

另一種是當前UI控件爲第一響應者 (把方法封裝在控件裏面)

具體看代碼,註釋裏我會詳細講解,如果實在不懂不妨動手敲一遍

  1. @interface ViewController ()  
  2. @property (weak, nonatomic) IBOutlet UILabel *label;  
  3. @end  
  4.    
  5. @implementation ViewController  
  6.    
  7. - (void)viewDidLoad {  
  8.     [super viewDidLoad];  
  9.    
  10.     //首先要允許label可以跟用戶交互  
  11.     self.label.userInteractionEnabled = YES;  
  12.     //給label添加一個敲擊手勢  
  13.     [self.label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];  
  14. }  
  15.    
  16. /** 點擊label觸發的方法 */  
  17. - (void)labelClick  
  18. {  
  19.     //控制器不需要調用這個方法, 但是其他亂七八糟的UI控件就需要調用這個方法 \  
  20.     因爲控制器默認是第一響應者  
  21.     //[self becomeFirstResponder];  
  22.    
  23.     //顯示menu 從來沒有讓menu跟控制器有關係 , 因爲是第一響應者, 所以會調用第一響應者的方法  
  24.    
  25.     //不一定調用控制器的方法, 因爲現在控制器是第一響應者  
  26.    
  27.    
  28.    
  29.     // 獲得菜單  
  30.     UIMenuController *menu = [UIMenuController sharedMenuController];  
  31.    
  32.     // 菜單最終顯示的位置  
  33.     CGRect rect = CGRectMake(100, 100, 100, 100);  
  34.     [menu setTargetRect:rect inView:self.label];  
  35.     //爲什麼要設置2個參數  爲了通用 \  
  36.     一個是矩形框, 一個是在哪個View上面  
  37.     //傳了矩形框, 要告訴座標原點在哪, 座標原點就在view上\  
  38.     以tagreView的左上角爲座標原點  
  39.     // 蘋果設計2個參數 是因爲矩形框一旦修改 出現的位置在哪裏都是可以的  
  40.    
  41.     /*  
  42.      targetRect:menuController指向的矩形框  
  43.      targetView:targetRect以targetView的左上角爲座標原點  
  44.      */  
  45.    
  46.     // 顯示菜單  
  47.     [menu setMenuVisible:YES animated:YES];  
  48.    
  49.     /*  
  50.      得通過第一響應者,來告訴MenuController它內部應該顯示什麼內容  
  51.      */  
  52. }  
  53.    
  54. #pragma mark - 第一響應者 + UIMenuController  
  55. /**  
  56.  * 說明控制器可以成爲第一響應者  
  57.  * 因爲控制器是因爲比較特殊的對象,它找控制器的方法,不找label的方法  
  58.  */  
  59. - (BOOL)canBecomeFirstResponder  
  60. {  
  61.     return YES;  
  62. }  
  63.    
  64. /**  
  65.  * 通過這個方法告訴UIMenuController它內部應該顯示什麼內容  
  66.  * 返回YES,就代表支持action這個操作  
  67.  */  
  68. - (BOOL)canPerformAction:(SEL)action withSender:(id)sender  
  69. {  
  70.     //打印, 將一個方法轉換成字符串 你就會看到許多方法  
  71.     NSLog(@"%@",NSStringFromSelector(action));  
  72.    
  73.        if (action == @selector(cut:)  
  74.         || action == @selector(copy:)  
  75.         || action == @selector(paste:)) {  
  76.         return YES;  
  77.     }  
  78.    
  79.     return NO;  
  80. }  
  81.    
  82. //監聽事情需要對應的方法 冒號之後傳入的是UIMenuController  
  83. - (void)cut:(UIMenuController *)menu  
  84. {  
  85.     NSLog(@"%s %@", __func__, menu);  
  86. }  
  87.    
  88. - (void)copy:(UIMenuController *)menu  
  89. {  
  90.     NSLog(@"%s %@", __func__, menu);  
  91. }  
  92.    
  93. - (void)paste:(UIMenuController *)menu  
  94. {  
  95.     NSLog(@"%s %@", __func__, menu);  
  96. }  
上面只是簡單的介紹了UIMenuController的基本知識,下面正在帶你運用到開發中的知識,封裝一個自定義控件裏面實現, 附上大概效果:


上代碼,代碼有具體的註釋,還有具體的用法,所以認真閱讀代碼即可,就不附上demo了

[html] view plain copy
  1. #import "JHLabel.h"  
  2.    
  3. @implementation JHLabel  
  4.    
  5. /** 不管控件是通過xib stroyboard 還是純代碼  提供兩種初始化的操作都調用同一個方法 */  
  6. - (instancetype)initWithFrame:(CGRect)frame  
  7. {  
  8.     if (self = [super initWithFrame:frame]) {  
  9.         [self setupTap];  
  10.     }  
  11.     return self;  
  12. }  
  13. /** 不管控件是通過xib stroyboard 還是純代碼  提供兩種初始化的操作都調用同一個方法 */  
  14. - (void)awakeFromNib  
  15. {  
  16.     [self setupTap];  
  17. }  
  18. /** 設置敲擊手勢 */  
  19. - (void)setupTap  
  20. {  
  21.    
  22.     self.text = @"author:會跳舞的獅子";  
  23.     //已經在stroyboard設置了與用戶交互,也可以用純代碼設置  
  24. //    self.userInteractionEnabled = YES;  
  25.    
  26.     //當前控件是label 所以是給label添加敲擊手勢  
  27.    [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];  
  28.    
  29. }  
  30. /** 點擊label觸發的方法 */  
  31. - (void)labelClick  
  32. {  
  33.     // 讓label成爲第一響應者 \  
  34.     一定要寫這句話  因爲這句話纔是主動讓label成爲第一響應者  
  35.     [self becomeFirstResponder];  
  36.    
  37.     // 獲得菜單  
  38.     UIMenuController *menu = [UIMenuController sharedMenuController];  
  39.    
  40.     // 設置菜單內容 \  
  41.     因爲menuItems是數組 官方沒有給出需要傳入什麼對象,但是以經驗可以判斷出需要傳入的是UIMenuItem對象 \  
  42.     而且顯示是按順序的  
  43.     menu.menuItems = @[  
  44.                        [[UIMenuItem alloc] initWithTitle:@"頂" action:@selector(ding:)],  
  45.                        [[UIMenuItem alloc] initWithTitle:@"回覆" action:@selector(reply:)],  
  46.                        [[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(warn:)]  
  47.                        ];  
  48.    
  49.     // 菜單最終顯示的位置 \  
  50.     有兩種方式: 一種是以自身的bounds  還有一種是以父控件的frame   
  51.     [menu setTargetRect:self.bounds inView:self];  
  52. //    [menu setTargetRect:self.frame inView:self.superview];  
  53.    
  54.     // 顯示菜單  
  55.     [menu setMenuVisible:YES animated:YES];  
  56. }  
  57.    
  58. #pragma mark - UIMenuController相關  
  59. /**  
  60.  * 讓Label具備成爲第一響應者的資格  
  61.  */  
  62. - (BOOL)canBecomeFirstResponder  
  63. {  
  64.     return YES;  
  65. }  
  66.    
  67. /**  
  68.  * 通過第一響應者的這個方法告訴UIMenuController可以顯示什麼內容  
  69.  */  
  70. - (BOOL)canPerformAction:(SEL)action withSender:(id)sender  
  71. {  
  72.     if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持複製  
  73.         || (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切  
  74.         || action == @selector(paste:)  
  75.         || action == @selector(ding:)  
  76.         || action == @selector(reply:)  
  77.         || action == @selector(warn:)) return YES;  
  78.    
  79.     return NO;  
  80. }  
  81.    
  82. #pragma mark - 監聽MenuItem的點擊事件  
  83. /** 剪切 */  
  84. - (void)cut:(UIMenuController *)menu  
  85. {  
  86.     //UIPasteboard 是可以在應用程序與應用程序之間共享的 \  
  87.     (應用程序:你的app就是一個應用程序 比如你的QQ消息可以剪切到百度查找一樣)  
  88.     // 將label的文字存儲到粘貼板  
  89.     [UIPasteboard generalPasteboard].string = self.text;  
  90.     // 清空文字  
  91.     self.text = nil;  
  92. }  
  93. /** 賦值 */  
  94. - (void)copy:(UIMenuController *)menu  
  95. {  
  96.     // 將label的文字存儲到粘貼板  
  97.     [UIPasteboard generalPasteboard].string = self.text;  
  98. }  
  99. /** 粘貼 */  
  100. - (void)paste:(UIMenuController *)menu  
  101. {  
  102.     // 將粘貼板的文字賦值給label  
  103.     self.text = [UIPasteboard generalPasteboard].string;  
  104. }  
  105.    
  106. //如果方法不實現,是不會顯示出來的  
  107. - (void)ding:(UIMenuController *)menu  
  108. {  
  109.     NSLog(@"%s %@", __func__, menu);  
  110. }  
  111.    
  112. - (void)reply:(UIMenuController *)menu  
  113. {  
  114.     NSLog(@"%s %@", __func__, menu);  
  115. }  
  116.    
  117. - (void)warn:(UIMenuController *)menu  
  118. {  
  119.     NSLog(@"%s %@", __func__, menu);  
  120. }  
  121. @end  
上面的代碼,menu只顯示在label的上面 而一般菜單欄我們都是顯示在cell的中間, 下面的這幅圖詳細講解了顯示在cell的中間


[html] view plain copy
  1. /** 點擊cell的時候調用 */  
  2. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  
  3. {  
  4.     // 取出cell  
  5.     UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];  
  6.    
  7.     UIMenuController *menu = [UIMenuController sharedMenuController];  
  8.    
  9.     // 設置菜單內容  
  10.     menu.menuItems = @[  
  11.                        [[UIMenuItem alloc] initWithTitle:@"頂" action:@selector(ding:)],  
  12.                        [[UIMenuItem alloc] initWithTitle:@"回覆" action:@selector(reply:)],  
  13.                        [[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(warn:)]  
  14.                        ];  
  15.    
  16.     // 顯示位置  
  17.     CGRect rect = CGRectMake(0, cell.height * 0.5, cell.width, 1);  
  18.     [menu setTargetRect:rect inView:cell];  
  19.    
  20.     // 顯示出來  
  21.     [menu setMenuVisible:YES animated:YES];  
  22. }  
  23.    
  24. #pragma mark - 獲得當前選中的評論  
  25. - (JHComment *)selectedComment  
  26. {  
  27.     // 獲得被選中的cell的行號  
  28.     NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;  
  29.     NSInteger row = indexPath.row;  
  30.    
  31.     // 獲得評論數據  
  32.     NSArray *comments = self.shortComments;  
  33.     if (indexPath.section == 0 && self.longComments.count) {  
  34.         comments = self.longComments;  
  35.     }  
  36.    
  37.     return comments[row];  
  38. }  
  39.    
  40. #pragma mark - UIMenuController處理  
  41. - (BOOL)canBecomeFirstResponder  
  42. {  
  43.     return YES;  
  44. }  
  45.    
  46. - (BOOL)canPerformAction:(SEL)action withSender:(id)sender  
  47. {  
  48.     if (!self.isFirstResponder) { // 文本框彈出鍵盤, 文本框纔是第一響應者  
  49.         if (action == @selector(ding:)  
  50.             || action == @selector(reply:)  
  51.             || action == @selector(warn:)) return NO;  
  52.         //如果是文本框,那麼這些顯示都不返回  
  53.     }  
  54.    
  55.     return [super canPerformAction:action withSender:sender];  
  56. }  
  57.    
  58. - (void)ding:(UIMenuController *)menu  
  59. {  
  60.     NSLog(@"ding - %@ %@",  
  61.            self.selectedComment.user.username,  
  62.            self.selectedComment.content);  
  63. }  
  64.    
  65. - (void)reply:(UIMenuController *)menu  
  66. {  
  67.     NSLog(@"reply - %@ %@",  
  68.            self.selectedComment.user.username,  
  69.            self.selectedComment.content);  
  70. }  
  71.    
  72. - (void)warn:(UIMenuController *)menu  
  73. {  
  74.     NSLog(@"warn - %@ %@",  
  75.            self.selectedComment.user.username,  
  76.            self.selectedComment.content);  
  77. }  
  78.    
  79. #注: 這裏的self.selectedComent  
  80. # (點語法  要麼調用set方法要麼調用get方法, 這裏直接用點語法是沒有提示的,我已經進行了聲明)  
  81. #/** 寫方法聲明的目的是爲了使用點語法提示 */  
  82. #- (JHComment *)selectedComment;  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章