温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

iOS开发之微信聊天页面怎么实现

发布时间:2021-01-30 10:12:54 来源:亿速云 阅读:253 作者:小新 栏目:移动开发

这篇文章主要介绍iOS开发之微信聊天页面怎么实现 ,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

聊天界面的效果图如下:在下面的聊天界面中中用到了3类cell,一类是显示文字和表情的,一类是显示录音的,一类是显示图片的。当点击图片时会跳转到另一个Controller中来进行图片显示,在图片显示页面中添加了一个捏合的手势。点击播放按钮,会播放录制的音频,cell的大学会根据内容的多少来调整,而cell中textView的高度是通过约束来设置的。

iOS开发之微信聊天页面怎么实现

  一,定义我们要用的cell,代码如下:

    1,显示表情和text的cell,代码如下,需要根据NSMutableAttributedString求出bound,然后改变cell上的ImageView和TextView的宽度的约束值,动态的调整气泡的大小,具体代码如下:

#import "TextCell.h" @interface TextCell() @property (strong, nonatomic) IBOutlet UIImageView *headImageView; @property (strong, nonatomic) IBOutlet UIImageView *chatBgImageView; @property (strong, nonatomic) IBOutlet UITextView *chatTextView; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *chatBgImageWidthConstraint; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *chatTextWidthConstaint; @property (strong, nonatomic) NSMutableAttributedString *attrString; @end @implementation TextCell -(void)setCellValue:(NSMutableAttributedString *)str {     //移除约束     [self removeConstraint:_chatBgImageWidthConstraint];     [self removeConstraint:_chatTextWidthConstaint];          self.attrString = str;     NSLog(@"%@",self.attrString);          //由text计算出text的宽高       CGRect bound = [self.attrString boundingRectWithSize:CGSizeMake(150, 1000) options:NSStringDrawingUsesLineFragmentOrigin context:nil];         //根据text的宽高来重新设置新的约束     //背景的宽     NSString *widthImageString;     NSArray *tempArray;          widthImageString = [NSString stringWithFormat:@"H:[_chatBgImageView(%f)]", bound.size.width+45];     tempArray = [NSLayoutConstraint constraintsWithVisualFormat:widthImageString options:0 metrics:0 views:NSDictionaryOfVariableBindings(_chatBgImageView)];     _chatBgImageWidthConstraint = tempArray[0];     [self addConstraint:self.chatBgImageWidthConstraint];          widthImageString = [NSString stringWithFormat:@"H:[_chatTextView(%f)]", bound.size.width+20];     tempArray = [NSLayoutConstraint constraintsWithVisualFormat:widthImageString options:0 metrics:0 views:NSDictionaryOfVariableBindings(_chatTextView)];     _chatBgImageWidthConstraint = tempArray[0];     [self addConstraint:self.chatBgImageWidthConstraint];          //设置图片     UIImage *image = [UIImage imageNamed:@"chatfrom_bg_normal.png"];     image = [image resizableImageWithCapInsets:(UIEdgeInsetsMake(image.size.height * 0.6, image.size.width * 0.4, image.size.height * 0.3, image.size.width * 0.4))];          //image = [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];                    [self.chatBgImageView setImage:image];          self.chatTextView.attributedText = str;           } @end

 2.显示图片的cell,通过block回调把图片传到Controller中,用于放大图片使用。

#import "MyImageCell.h" @interface MyImageCell() @property (strong, nonatomic) IBOutlet UIImageView *bgImageView; @property (strong, nonatomic) IBOutlet UIButton *imageButton; @property (strong, nonatomic) ButtonImageBlock imageBlock; @property (strong, nonatomic) UIImage *buttonImage; @end @implementation MyImageCell -(void)setCellValue:(UIImage *)sendImage {     self.buttonImage = sendImage;     UIImage *image = [UIImage imageNamed:@"chatto_bg_normal.png"];     image = [image resizableImageWithCapInsets:(UIEdgeInsetsMake(image.size.height * 0.6, image.size.width * 0.4, image.size.height * 0.3, image.size.width * 0.4))];     [self.bgImageView setImage:image];     [self.imageButton setImage:sendImage forState:UIControlStateNormal]; } -(void)setButtonImageBlock:(ButtonImageBlock)block {     self.imageBlock = block; } - (IBAction)tapImageButton:(id)sender {     self.imageBlock(self.buttonImage); } @end

 3.显示录音的cell,点击cell上的button,播放对应的录音,代码如下:

#import "VoiceCellTableViewCell.h" @interface VoiceCellTableViewCell() @property (strong, nonatomic) NSURL *playURL; @property (strong, nonatomic) AVAudioPlayer *audioPlayer; @end @implementation VoiceCellTableViewCell -(void)setCellValue:(NSDictionary *)dic {     _playURL = dic[@"body"][@"content"]; } - (IBAction)tapVoiceButton:(id)sender {               NSError *error = nil;     AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:_playURL error:&error];     if (error) {         NSLog(@"播放错误:%@",[error description]);     }     self.audioPlayer = player;     [self.audioPlayer play]; } @end

二,cell搞定后要实现我们的ChatController部分    

ChatController.m中的延展和枚举代码如下:

//枚举Cell类型 typedef enum : NSUInteger {     SendText,     SendVoice,     SendImage } MySendContentType; //枚举用户类型 typedef enum : NSUInteger {     MySelf,     MyFriend } UserType; @interface ChatViewController () //工具栏 @property (nonatomic,strong) ToolView *toolView; //音量图片 @property (strong, nonatomic) UIImageView *volumeImageView; //工具栏的高约束,用于当输入文字过多时改变工具栏的约束 @property (strong, nonatomic) NSLayoutConstraint *tooViewConstraintHeight; //存放所有的cell中的内容 @property (strong, nonatomic) NSMutableArray *dataSource; //storyBoard上的控件 @property (strong, nonatomic) IBOutlet UITableView *myTableView; //用户类型 @property (assign, nonatomic) UserType userType; //从相册获取图片 @property (strong, nonatomic) UIImagePickerController *imagePiceker; @end

实现工具栏中的回调的代码如下,通过Block,工具栏和ViewController交互

//实现工具栏的回调 -(void)setToolViewBlock {     __weak __block ChatViewController *copy_self = self;     //通过block回调接收到toolView中的text     [self.toolView setMyTextBlock:^(NSString *myText) {         NSLog(@"%@",myText);                  [copy_self sendMessage:SendText Content:myText];     }];               //回调输入框的contentSize,改变工具栏的高度     [self.toolView setContentSizeBlock:^(CGSize contentSize) {          [copy_self updateHeight:contentSize];     }];               //获取录音声量,用于声音音量的提示     [self.toolView setAudioVolumeBlock:^(CGFloat volume) {                  copy_self.volumeImageView.hidden = NO;         int index = (int)(volume*100)%6+1;         [copy_self.volumeImageView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"record_animate_%02d.png",index]]];     }];          //获取录音地址(用于录音播放方法)     [self.toolView setAudioURLBlock:^(NSURL *audioURL) {         copy_self.volumeImageView.hidden = YES;                  [copy_self sendMessage:SendVoice Content:audioURL];     }];          //录音取消(录音取消后,把音量图片进行隐藏)     [self.toolView setCancelRecordBlock:^(int flag) {         if (flag == 1) {             copy_self.volumeImageView.hidden = YES;         }     }];               //扩展功能回调     [self.toolView setExtendFunctionBlock:^(int buttonTag) {         switch (buttonTag) {             case 1:                 //从相册获取                 [copy_self presentViewController:copy_self.imagePiceker animated:YES completion:^{                                      }];                 break;             case 2:                 //拍照                 break;                              default:                 break;         }     }]; }

把聊天工具栏中返回的内容显示在tableView中,代码如下:

//发送消息 -(void)sendMessage:(MySendContentType) sendType Content:(id)content {          //把收到的url封装成字典     UserType userType = self.userType;          NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:2];     [tempDic setValue:@(userType) forKey:@"userType"];          NSDictionary *bodyDic = @{@"type":@(sendType),                               @"content":content};     [tempDic setValue:bodyDic forKey:@"body"];     [self.dataSource addObject:tempDic];          //重载tableView     [self.myTableView  reloadData];          NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataSource.count-1 inSection:0];          [self.myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];        }

根据ToolView中回调接口,获取工具栏中textView的ContentSize,通过ContentSize来调整ToolView的高度约束,代码如下:

//更新toolView的高度约束 -(void)updateHeight:(CGSize)contentSize {     float height = contentSize.height + 18;     if (height <= 80) {         [self.view removeConstraint:self.tooViewConstraintHeight];                  NSString *string = [NSString stringWithFormat:@"V:[_toolView(%f)]", height];                  NSArray * tooViewConstraintV = [NSLayoutConstraint constraintsWithVisualFormat:string options:0 metrics:0 views:NSDictionaryOfVariableBindings(_toolView)];         self.tooViewConstraintHeight = tooViewConstraintV[0];         [self.view addConstraint:self.tooViewConstraintHeight];     } }

从本地获取图片,并显示在相应的Cell上,代码如下:

//获取图片后要做的方法 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {     UIImage *pickerImage = info[UIImagePickerControllerEditedImage];          //发送图片     [self sendMessage:SendImage Content:pickerImage];          [self dismissViewControllerAnimated:YES completion:^{}];      } -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {     //在ImagePickerView中点击取消时回到原来的界面     [self dismissViewControllerAnimated:YES completion:^{}]; }

把NSString 转换成NSMutableAttributeString,用于显示表情,代码如下:

//显示表情,用属性字符串显示表情 -(NSMutableAttributedString *)showFace:(NSString *)str {     //加载plist文件中的数据     NSBundle *bundle = [NSBundle mainBundle];     //寻找资源的路径     NSString *path = [bundle pathForResource:@"emoticons" ofType:@"plist"];     //获取plist中的数据     NSArray *face = [[NSArray alloc] initWithContentsOfFile:path];          //创建一个可变的属性字符串          NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:str];          UIFont *baseFont = [UIFont systemFontOfSize:17];     [attributeString addAttribute:NSFontAttributeName value:baseFont                        range:NSMakeRange(0, str.length)];          //正则匹配要替换的文字的范围     //正则表达式     NSString * pattern = @"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]";     NSError *error = nil;     NSRegularExpression * re = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];          if (!re) {         NSLog(@"%@", [error localizedDescription]);     }          //通过正则表达式来匹配字符串     NSArray *resultArray = [re matchesInString:str options:0 range:NSMakeRange(0, str.length)];               //用来存放字典,字典中存储的是图片和图片对应的位置     NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];          //根据匹配范围来用图片进行相应的替换     for(NSTextCheckingResult *match in resultArray) {         //获取数组元素中得到range         NSRange range = [match range];                  //获取原字符串中对应的值         NSString *subStr = [str substringWithRange:range];                  for (int i = 0; i < face.count; i ++)         {             if ([face[i][@"chs"] isEqualToString:subStr])             {                                  //face[i][@"gif"]就是我们要加载的图片                 //新建文字附件来存放我们的图片                 NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];                                  //给附件添加图片                 textAttachment.image = [UIImage imageNamed:face[i][@"png"]];                                  //把附件转换成可变字符串,用于替换掉源字符串中的表情文字                 NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];                                  //把图片和图片对应的位置存入字典中                 NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];                 [imageDic setObject:imageStr forKey:@"image"];                 [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];                                  //把字典存入数组中                 [imageArray addObject:imageDic];                              }         }     }          //从后往前替换     for (int i = imageArray.count -1; i >= 0; i--)     {         NSRange range;         [imageArray[i][@"range"] getValue:&range];         //进行替换         [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];              }          return  attributeString; }

根据Cell显示内容来调整Cell的高度,代码如下:

//调整cell的高度 -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {          //根据文字计算cell的高度     if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendText)]) {         NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]];                  CGRect textBound = [contentText boundingRectWithSize:CGSizeMake(150, 1000) options:NSStringDrawingUsesLineFragmentOrigin context:nil];                  float height = textBound.size.height + 40;         return height;     }     if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendVoice)])     {         return 73;     }          if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendImage)])     {         return 125;     }          return 100;  }

根据cell内容和用户类型,来选择Cell,代码如下:

//设置cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {     //根据类型选cell     MySendContentType contentType = [self.dataSource[indexPath.row][@"body"][@"type"] integerValue];               if ([self.dataSource[indexPath.row][@"userType"]  isEqual: @(MyFriend)]) {         switch (contentType) {             case SendText:             {                 TextCell *cell = [tableView dequeueReusableCellWithIdentifier:@"textCell" forIndexPath:indexPath];                 NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]];                 [cell setCellValue:contentText];                 return cell;             }                 break;                              case SendImage:             {                 heImageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"heImageCell" forIndexPath:indexPath];                 [cell setCellValue:self.dataSource[indexPath.row][@"body"][@"content"]];                                                   __weak __block ChatViewController *copy_self = self;                                  //传出cell中的图片                 [cell setButtonImageBlock:^(UIImage *image) {                     [copy_self displaySendImage:image];                 }];                 return cell;             }                 break;                              case SendVoice:             {                 VoiceCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"heVoiceCell" forIndexPath:indexPath];                 [cell setCellValue:self.dataSource[indexPath.row]];                 return cell;             }                 break;                              default:                 break;         }     }              if ([self.dataSource[indexPath.row][@"userType"]  isEqual: @(MySelf)]) {              switch (contentType) {             case SendText:             {                 TextCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myselfTextCell" forIndexPath:indexPath];                 NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]];                 [cell setCellValue:contentText];                 return cell;             }             break;                          case SendImage:             {                 MyImageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myImageCell" forIndexPath:indexPath];                 [cell setCellValue:self.dataSource[indexPath.row][@"body"][@"content"]];                                  __weak __block ChatViewController *copy_self = self;                                  //传出cell中的图片                 [cell setButtonImageBlock:^(UIImage *image) {                     [copy_self displaySendImage:image];                 }];                                  return cell;             }                 break;                          case SendVoice:             {                 VoiceCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myVoiceCell" forIndexPath:indexPath];                 [cell setCellValue:self.dataSource[indexPath.row]];                 return cell;             }                 break;                              default:                 break;         }     }     UITableViewCell *cell;     return cell; }

点击发送的图片来放大图片代码如下:

//发送图片的放大 -(void) displaySendImage : (UIImage *)image {     //把照片传到放大的controller中     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];          ImageViewController *imageController = [storyboard instantiateViewControllerWithIdentifier:@"imageController"];     [imageController setValue:image forKeyPath:@"image"];         [self.navigationController pushViewController:imageController animated:YES];      }

根据键盘的高度来调整ToolView的位置,代码如下:

//键盘出来的时候调整tooView的位置 -(void) keyChange:(NSNotification *) notify {     NSDictionary *dic = notify.userInfo;               CGRect endKey = [dic[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue];     //坐标系的转换     CGRect endKeySwap = [self.view convertRect:endKey fromView:self.view.window];     //运动时间     [UIView animateWithDuration:[dic[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{                  [UIView setAnimationCurve:[dic[UIKeyboardAnimationCurveUserInfoKey] doubleValue]];         CGRect frame = self.view.frame;                  frame.size.height = endKeySwap.origin.y;                  self.view.frame = frame;         [self.view layoutIfNeeded];     }]; }

代码有点多,不过在关键的部分都加有注释,在图片显示View中通过捏合手势来调整图片的大小,代码如下:

- (IBAction)tapPichGesture:(id)sender {     UIPinchGestureRecognizer *gesture = sender;          //手势改变时     if (gesture.state == UIGestureRecognizerStateChanged)     {                  //捏合手势中scale属性记录的缩放比例         self.myImageView.transform = CGAffineTransformMakeScale(gesture.scale, gesture.scale);     }      }

以上是“iOS开发之微信聊天页面怎么实现 ”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI