你的位置:首页 > 操作系统

[操作系统]iOS IM开发建议(四)UIMenuController 怎么使用

  这应该是这个系列最后一篇了。我写了很多都不是很好,不过如果不写,那就永远写不好。欢迎大家交流纠错。

 

  UIMenuController,它不像Alert那么不友好,也不像ActionSheet,一定要点击一下;你可以无视它的出现,也可以通过它调用一些设定好的方法。它就长这样:

  

  这个控件是不是很熟悉,微信里面你长按就回出现的一个view。做IM的话,标杆就是wechat了,所以你们的产品怎么会放过它(你)呢。

  先设计一个我们常用的场景:你在聊天界面,长按textView,然后弹出这个菜单,接着你点击了某一个Item。

  聊天页面:tableView + inputBar(就是有输入框的一个view啦)。

  这里面你会用到,tableView的的代理,要实现几个delegate。

 1 #pragma mark - UITableViewDataSource & UITableViewDelegate 2 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 3   // 有多少条数据 4   return [dataArray count]; 5 } 6  7 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 8   static NSString * CellIdentifier = @"MessageCell"; 9   MessageCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];10   if (cell == nil) {11     cell = [MessageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];12     cell.selectionStyle = UITableViewCellSelectionStyleDefault;13   }14   MessageModel * model = [dataArray objectAtIndex:indexPath.row];15   [cell setMyContent:model];16   return cell;17 }18 19 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {20   // 这里就用之前写到的的高度计算21   return #cellHeightFromModelData#;22 }

  那我们再来看一下cell,cell要做几件事:1、自己的frame要算出来;2、要放好textView或imageView,我这里只说一下textView咯;

  .h 我们要声明一个public的方法,用model来设置cell,减少VC的代码量。 还有一个block,给VC回传textView交互事件。

 1 typedef NS_ENUM(NSInteger,CellOperations) { 2   TextCopy, 3   TextDelete, 4   TextTransfor, 5   TextCollection, 6  7   ImageCopy, 8   ImageDelete, 9   ImageTransfor,10   ImageCollection,11 };12 13 @property(nonatomic,copy)void (^CellOperation)(MessageModel* message, CellOperations cop);14 15 - (void)setMyContent:(MessageModel *)message;

  .m 我们要算自己的高度,textView的高度。还有传递textView的一些事件到VC上。

 1 - (void)setMyContent:(MessageModel *)message { 2   // 传递参数 3   // 算高度 4   // 设置textView的大小 以及背景框的大小 5 } 6  7 - (void)textViewCallBack:(CellOperations cop){ 8   // 把textView的操作 截获  9   // 调用自己的 callBackVC 将操作传递出去10 }11 12 - (void)callBackVC:(CellOperations cop){13   // 往VC传递操作事件14 }

  实现上面的3个方法,我们就可以绘制出Cell,并且可以传递textView的操作了。

  接下来,textView。

  .h  这里我们要声明一个Block 给Cell传值

@property(nonatomic,copy)void (^TVOperation)(CellOperations cop);

  .m 这是就要实现UIMenuController

 1 // 2 // DisplayTextView.m 3 //  4 // 5 // Created by akforsure on 15/12/1. 6 // Copyright © 2015年 akforsure. All rights reserved. 7 // 8  9 #import "DisplayTextView.h" 10  11 @implementation DisplayTextView { 12   UIMenuController * menu; 13 } 14 - (instancetype)initWithFrame:(CGRect)frame { 15   self = [super initWithFrame:frame]; 16   if(self) { 17     // 展示用的textView 要不能编辑 最好也不能选取,不然很二的 18     self.editable = NO; 19     self.selectable = NO; 20   } 21   return self; 22 } 23 - (void)showMenu{ 24   // 如果已经出现了 我们就return 25   if([menu isMenuVisible]) return; 26   // textView 一定要是第一响应 也要设置为可以是第一响应 27   [self becomeFirstResponder]; 28   // 设置UIMenuItems 并且添加到页面上 29   UIMenuItem *menuItem0 = [[UIMenuItem alloc]initWithTitle:@"复制" action:@selector(kCopy:)]; 30   UIMenuItem *menuItem1 = [[UIMenuItem alloc]initWithTitle:@"删除" action:@selector(kDelete:)]; 31   UIMenuItem *menuItem2 = [[UIMenuItem alloc]initWithTitle:@"转发" action:@selector(transfor:)]; 32   UIMenuItem *menuItem3 = [[UIMenuItem alloc]initWithTitle:@"收藏" action:@selector(collection:)]; 33   menu = [UIMenuController sharedMenuController]; 34   [menu setMenuItems:[NSArray arrayWithObjects:menuItem0,menuItem1,menuItem2,menuItem3,nil]]; 35   [menu setTargetRect:self.bounds inView:self]; 36   [menu setMenuVisible: YES animated: YES]; 37 } 38 // 这个方法一定要实现的 不然你无法响应你的操作 39 - (BOOL)canBecomeFirstResponder { 40   return YES; 41 } 42 // 这个方法是对点击的响应 返回YES 就是可以被识别  43 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 44  45   if(action == @selector(kCopy:)) { 46     return YES; 47   }else if (action == @selector(kDelete:)) { 48     return YES; 49   }else if (action == @selector(transfor:)) { 50     return YES; 51   } 52   else if (action == @selector(collection:)) { 53     return YES; 54   } 55   [super canPerformAction:action withSender:sender]; 56   return NO; 57 } 58 #pragram mark - private methods 每一个事件的实现 59 - (void)kCopy:(id)sender { 60   if(self.TVOperation){ 61     self.TVOperation(TextCopy); 62   } 63   NSLog(@"textkCopy"); 64 } 65 - (void)kDelete:(id)sender { 66   if(self.TVOperation){ 67     self.TVOperation(TextDelete); 68   } 69   NSLog(@"textkDelete"); 70 } 71 - (void)transfor:(id)sender { 72   if(self.TVOperation){ 73     self.TVOperation(TextTransfor); 74   } 75   NSLog(@"texttransfor"); 76 } 77 - (void)collection:(id)sender { 78   if(self.TVOperation){ 79     self.TVOperation(TextCollection); 80   } 81   NSLog(@"textcollection"); 82 } 83  84  85 // Only override drawRect: if you perform custom drawing. 86 // An empty implementation adversely affects performance during animation. 87 // 在draw的时候加入long press 手势 88 - (void)drawRect:(CGRect)rect { 89   // Drawing code 90   // 去除 长按手势 91   for ( UIGestureRecognizer *recognizer in self.gestureRecognizers) { 92     if ( [recognizer isKindOfClass:[UILongPressGestureRecognizer class]]) { 93       recognizer.enabled = NO; 94       //这里可能有问题,我不是很确定 不过用了一段时间也没啥 95     } 96   } 97   // 重新加入长按手势 98   UILongPressGestureRecognizer *kGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showMenu)]; 99   [self addGestureRecognizer:kGesture];100 }101 102 @end

  到这里为止,我们就完成了你看到的那个效果了,我没有给全所有代码,因为我希望大家都自己动手写一下。