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

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

 

posted @ 2016-05-31 19:41  akforsure  阅读(1207)  评论(0编辑  收藏  举报