这应该是这个系列最后一篇了。我写了很多都不是很好,不过如果不写,那就永远写不好。欢迎大家交流纠错。
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
到这里为止,我们就完成了你看到的那个效果了,我没有给全所有代码,因为我希望大家都自己动手写一下。