您好,登錄后才能下訂單哦!
這篇文章主要介紹iOS開發之微信聊天頁面怎么實現 ,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
聊天界面的效果圖如下:在下面的聊天界面中中用到了3類cell,一類是顯示文字和表情的,一類是顯示錄音的,一類是顯示圖片的。當點擊圖片時會跳轉到另一個Controller中來進行圖片顯示,在圖片顯示頁面中添加了一個捏合的手勢。點擊播放按鈕,會播放錄制的音頻,cell的大學會根據內容的多少來調整,而cell中textView的高度是通過約束來設置的。
一,定義我們要用的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開發之微信聊天頁面怎么實現 ”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。