本文共 11536 字,大约阅读时间需要 38 分钟。
有的内容是我从别的博客中看到的,如有侵权请私聊我
有些我认为不太容易理解的方法在代码中也会有注释boundingRectWithSize: options: attributes: context:
用于计算自适应高度 P1:文本显示的最大宽度和最大高度 P2:计算的类型 NSStringDrawingUsesLineFragmentOrigin 绘制文本时使用,一般使用这项 P3:文本属性 P4:包括一些信息,例如如何调整字间距以及缩放。该参数一般可为 nilNSDictionary *attri = @{NSFontAttributeName:[UIFont systemFontOfSize:18]};
设置字典数组字体大小为18 另外, 方法 NSForegroundColorAttributeName 为设置字典数组字体颜色 NSBackgroundColorAttributeName: 设置背景颜色insertRowsAtIndexPaths: withRowAnimation:
在索引路径处插入行 P1: 想要该行数之后 P2: 指定插入单元格时要执行的动画类型 此处我们使用UITableViewRowAnimationBottom动画类型,从底部滑入或滑出 另外: UITableViewRowAnimationFade, 淡入或淡出UITableViewRowAnimationRight, 从右侧滑入或滑出 UITableViewRowAnimationLeft,从左侧滑入或滑出UITableViewRowAnimationTop, 从顶部滑入或滑出UITableViewRowAnimationBottom, 从底部滑入或滑出UITableViewRowAnimationNone, 使用默认动画,上部或下部cell,上下移动覆盖掉要删除的cell 可参考简书 :NSNotificationCenter
观察者,在该代码中我们用于监测键盘的弹出及回收 具体了解可看苹果公司:scrollToRowAtIndexPath: atScrollPosition: animated:
滚动视图至指定位置,该代码中我们用它来滚动视图(随着消息上移) P1: 索引行 P2:标识row滚动结束时表视图中的相对位置 P3: 是否产生动画效果(即缓冲) 另外: UITableViewScrollPositionNone 表格视图以最小的移动滚动感兴趣的行,使其完全可见。如果该行已完全可见,则不会进行滚动 UITableViewScrollPositionTop 表视图将感兴趣的行滚动到可见表视图的顶部。 UITableViewScrollPositionMiddle 表视图将感兴趣的行滚动到可见表视图的中间。 UITableViewScrollPositionBottom 表视图将感兴趣的行滚动到可见表视图的底部。animateWithDuration: animations:
P1:动画持续时间 P2:方法, 这里让视图恢复原来的位置就好前面说了这么多,下来放代码
此处我采用导航栏跳转的方式跳转至该界面,在第一个界面中设置点击跳转事件就好
ViewController.m 里:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. ChatViewController *chat = [[ChatViewController alloc] init]; _nav = [[UINavigationController alloc] initWithRootViewController:chat];}- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event { [self presentViewController:_nav animated:NO completion:nil];}
下来在 ChatViewController.h 中声明需要的属性及协议:
@interface ChatViewController : UIViewController@property UITextField *textField;@property UITableView *tableView;@property NSMutableArray *messageArr;@property (nonatomic) NSNumber *rowHeight;@property NSMutableArray *rowHeightArr;
在 ChatViewController.m 里写具体操作:
首先,为了方便起见,宏定义屏幕的宽高
#define W ([UIScreen mainScreen].bounds.size.width)#define H ([UIScreen mainScreen].bounds.size.height)
在 - (void)viewDidLoad 里初始化
self.view.backgroundColor = [UIColor whiteColor]; self.navigationController.navigationBar.barTintColor = [UIColor colorWithRed:0.21 green:0.56 blue:0.8 alpha:1.0]; self.navigationItem.title = @"chat"; [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor], NSForegroundColorAttributeName:[UIFont systemFontOfSize:18]}]; //导航栏左侧按钮 UIButton *backbutton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; [backbutton setImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal]; [backbutton addTarget:self action:@selector(back) forControlEvents:UIControlEventAllTouchEvents]; UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:backbutton]; self.navigationItem.leftBarButtonItem = backItem; //设置输入框 _textField = [[UITextField alloc] initWithFrame:CGRectMake(W * 0.07, H * 0.94, W * 0.75, H * 0.06)]; _textField.borderStyle = UITextBorderStyleRoundedRect; _textField.layer.borderColor = [UIColor blackColor].CGColor; _textField.delegate = self; //设置发送按钮 UIButton *sendButton = [UIButton buttonWithType:UIButtonTypeCustom]; sendButton.backgroundColor = [UIColor colorWithRed:0.27 green:0.55 blue:0.8 alpha:1.0]; [sendButton setTitle:@"发送" forState:UIControlStateNormal]; [sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [sendButton addTarget:self action:@selector(send) forControlEvents:UIControlEventTouchDown]; sendButton.frame = CGRectMake(W * 0.83, H * 0.94, W * 0.15, H * 0.06); sendButton.layer.borderWidth = 1; sendButton.layer.cornerRadius = 10; /* UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, W, H - 108)]; view.backgroundColor = [UIColor blackColor]; view.tag = 101;*/ [self.view addSubview:_textField]; [self.view addSubview:sendButton]; _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, W, H - 88) style:UITableViewStylePlain]; _tableView.delegate = self; _tableView.dataSource = self; //设置分割线(设置为无样式) _tableView.separatorStyle = UITableViewCellAccessoryNone; _tableView.showsVerticalScrollIndicator = NO; [self.view addSubview:_tableView];// [self.view addSubview:view];// [self.view bringSubviewToFront:view]; //设置聊天信息数值 _messageArr = [NSMutableArray arrayWithObjects:@"选择总是会有代价的,承受它就好了", @"当你见到我时,我已是更好的自己", @"自律并不是一个什么远在天边的大词儿,它是你每一天每一分钟,能在那些不想做的一瞬间,说服自己咬着牙继续坚持下去", @"永远有期待", nil]; _rowHeightArr = [[NSMutableArray alloc] init]; for (NSString *str in _messageArr) { //因为boundingRectWithSize: options: attributes: context: 函数中参数三需要使用字典数组 //P1:文本显示的最大宽度和最大高度 //P2:计算的类型 NSStringDrawingUsesLineFragmentOrigin 绘制文本时使用,一般使用这项 //P3:文本属性 //P4:包括一些信息,例如如何调整字间距以及缩放。该参数一般可为 nil NSDictionary *attri = @{NSFontAttributeName:[UIFont systemFontOfSize:18]}; CGSize size = [str boundingRectWithSize:CGSizeMake(W * 0.6, H * 0.41) options:NSStringDrawingUsesLineFragmentOrigin attributes:attri context:nil].size; //聊天框高度,+ W * 0.15为了保持会话之间的距离 int height = size.height + W * 0.15; _rowHeight = [NSNumber numberWithInt:height]; //存储在数组里,设置行高时使用 [_rowHeightArr addObject:_rowHeight]; } //监视键盘回收 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillDisAppear:) name:UIKeyboardWillHideNotification object:nil];
创建button发送事件
- (void)send{ [_messageArr addObject:_textField.text]; NSDictionary *attri = @{NSFontAttributeName:[UIFont systemFontOfSize:18]}; //自适应高度,并计算 CGSize size = [_textField.text boundingRectWithSize:CGSizeMake(W * 0.6, H * 0.58) options:NSStringDrawingUsesLineFragmentOrigin attributes:attri context:nil].size; int height = size.height + W * 0.15; _rowHeight = [NSNumber numberWithInt:height]; [_rowHeightArr addObject:_rowHeight]; //_messageArr.count - 1 : 显示的最后一行 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(_messageArr.count - 1) inSection:0]; //加入一个cell [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; //更新tableView [_tableView reloadData]; //滚动界面(随着消息发送上移) [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; //清空textField _textField.text = @""; }
!!!!!!核心: cell的使用:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellId = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if(!cell){ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId]; } else { //tableView的复用,如果不删除,会出现bug //删除cell所有的子视图 while ([cell.contentView.subviews lastObject] != nil) { [(UIView *)[cell.contentView.subviews lastObject] removeFromSuperview]; } } //分割线风格(无显示) cell.selectionStyle = UITableViewCellSelectionStyleNone; //一人一句话 if(indexPath.row % 2 != 0){ //设置头像 UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed: @"image1.jpg"]]; imageView.frame = CGRectMake(W * 0.01, W * 0.05, W * 0.1, W * 0.1); [cell.contentView addSubview:imageView]; //设置对话框 UILabel *label = [[UILabel alloc] init]; label.numberOfLines = 0; label.text = _messageArr[indexPath.row]; label.font = [UIFont systemFontOfSize:18]; NSDictionary *attri = @{NSFontAttributeName:label.font}; //自适应高度 CGSize size = [label.text boundingRectWithSize:CGSizeMake(W * 0.6, H * 0.58) options:NSStringDrawingUsesLineFragmentOrigin attributes:attri context:nil].size; label.frame = CGRectMake(W * 0.13, W * 0.07, size.width, size.height + W * 0.05); //设置聊天气泡 UIImageView *imageViewBubble = [[UIImageView alloc] init]; imageViewBubble.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.94 alpha:1.0]; imageViewBubble.frame = CGRectMake(W * 0.12, W * 0.07, size.width + W * 0.05, size.height + W * 0.03); [cell.contentView addSubview:imageViewBubble]; [cell.contentView addSubview:label]; } else { UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image5.jpg"]]; imageView.frame = CGRectMake(W * 0.89, W * 0.01, W * 0.1, W * 0.1); [cell.contentView addSubview:imageView]; UILabel *label = [[UILabel alloc] init]; label.numberOfLines = 0; label.text = _messageArr[indexPath.row]; label.font = [UIFont systemFontOfSize:18]; NSDictionary *attri = @{NSFontAttributeName:label.font}; CGSize size = [label.text boundingRectWithSize:CGSizeMake(W * 0.6, H * 0.58) options:NSStringDrawingUsesLineFragmentOrigin attributes:attri context:nil].size; label.frame = CGRectMake(W * 0.86 - size.width, W * 0.05, size.width, size.height); UIImageView *imageViewBubble = [[UIImageView alloc] init]; imageViewBubble.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.94 alpha:1.0]; imageViewBubble.frame = CGRectMake(W * 0.82 - size.width, W * 0.03, size.width + W * 0.05, size.height + W * 0.03); [cell.contentView addSubview:imageViewBubble]; [cell.contentView addSubview:label]; } return cell; }//设置单元格高度- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ //将NSNumber型的height转换为CGFloat型 CGFloat height = [_rowHeightArr[indexPath.row] floatValue]; return height;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _messageArr.count;}
下来回收键盘:
//显示简单的键盘回收- (void)keyboardWillDisAppear:(NSNotification *)notification{ //第一个参数是动画持续时间 //第二个参数是方法,这里让视图恢复原来的位置就好 [UIView animateWithDuration:1 animations:^{self.view.transform = CGAffineTransformMakeTranslation(0, 0);}]; }- (void)keyboardWillAppear:(NSNotification *)notification{ //计算键盘高度 CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat keyboardY = keyboardFrame.origin.y; //视图整体上升 [UIView animateWithDuration:1.0 animations:^{self.view.transform = CGAffineTransformMakeTranslation(0, keyboardY - self.view.frame.size.height);}];}//点击空白处回收键盘- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{ [_textField endEditing:YES];}//点击return回收键盘- (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField endEditing:YES]; return YES;}
最后加上返回按钮事件:
- (void)back{ [self dismissViewControllerAnimated:NO completion:nil];}
这是我在初始化时加入的话:
这是我发送几句话后的效果: 若不清除cell的子视图,则会产生这样的bug:转载地址:http://dukti.baihongyu.com/