国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

iOS開發之微信聊天頁面實現

2019-11-14 20:01:23
字體:
來源:轉載
供稿:網友

  在上篇博客iOS開發之微信聊天工具欄的封裝中對微信聊天頁面下方的工具欄進行了封裝,本篇博客中就使用之前封裝的工具欄來進行聊天頁面的編寫。在聊天頁面中主要用到了TableView的知識,還有如何在倆天中顯示我們發送的表情,具體請參考之前的博客:IOS開發之顯示微博表情,在這兒就不做贅述啦。在聊天頁面用到了三對,六種Cell,不過cell的復雜度要比之前的新浪微博(IOS開發之新浪圍脖)簡單的多。廢話少說吧,還是先來幾張效果圖,在給出實現代碼吧。

  聊天界面的效果圖如下:在下面的聊天界面中中用到了3類cell,一類是顯示文字和表情的,一類是顯示錄音的,一類是顯示圖片的。當點擊圖片時會跳轉到另一個Controller中來進行圖片顯示,在圖片顯示頁面中添加了一個捏合的手勢(關于手勢,請參考:iOS開發之手勢識別)。點擊播放按鈕,會播放錄制的音頻,cell的大學會根據內容的多少來調整,而cell中textView的高度是通過約束來設置的。

  一,定義我們要用的cell,代碼如下:

    1,顯示表情和text的cell,代碼如下,需要根據NSMutableAttributedString求出bound,然后改變cell上的ImageView和TextView的寬度的約束值,動態的調整氣泡的大小,具體代碼如下:

 1 #import "TextCell.h" 2  3 @interface TextCell() 4  5 @PRoperty (strong, nonatomic) IBOutlet UIImageView *headImageView; 6 @property (strong, nonatomic) IBOutlet UIImageView *chatBgImageView; 7 @property (strong, nonatomic) IBOutlet UITextView *chatTextView; 8 @property (strong, nonatomic) IBOutlet NSLayoutConstraint *chatBgImageWidthConstraint; 9 @property (strong, nonatomic) IBOutlet NSLayoutConstraint *chatTextWidthConstaint;10 @property (strong, nonatomic) NSMutableAttributedString *attrString;11 12 @end13 14 @implementation TextCell15 16 -(void)setCellValue:(NSMutableAttributedString *)str17 {18     //移除約束19     [self removeConstraint:_chatBgImageWidthConstraint];20     [self removeConstraint:_chatTextWidthConstaint];21     22     self.attrString = str;23     NSLog(@"%@",self.attrString);24     25     //由text計算出text的寬高26       CGRect bound = [self.attrString boundingRectWithSize:CGSizeMake(150, 1000) options:NSStringDrawingUsesLineFragmentOrigin context:nil];27    28     //根據text的寬高來重新設置新的約束29     //背景的寬30     NSString *widthImageString;31     NSArray *tempArray;32     33     widthImageString = [NSString stringWithFormat:@"H:[_chatBgImageView(%f)]", bound.size.width+45];34     tempArray = [NSLayoutConstraint constraintsWithVisualFormat:widthImageString options:0 metrics:0 views:NSDictionaryOfVariableBindings(_chatBgImageView)];35     _chatBgImageWidthConstraint = tempArray[0];36     [self addConstraint:self.chatBgImageWidthConstraint];37     38     widthImageString = [NSString stringWithFormat:@"H:[_chatTextView(%f)]", bound.size.width+20];39     tempArray = [NSLayoutConstraint constraintsWithVisualFormat:widthImageString options:0 metrics:0 views:NSDictionaryOfVariableBindings(_chatTextView)];40     _chatBgImageWidthConstraint = tempArray[0];41     [self addConstraint:self.chatBgImageWidthConstraint];42     43     //設置圖片44     UIImage *image = [UIImage imageNamed:@"chatfrom_bg_normal.png"];45     image = [image resizableImageWithCapInsets:(UIEdgeInsetsMake(image.size.height * 0.6, image.size.width * 0.4, image.size.height * 0.3, image.size.width * 0.4))];46     47     //image = [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];48     49     50     51     [self.chatBgImageView setImage:image];52     53     self.chatTextView.attributedText = str;54     55     56 }57 58 @end
View Code

    2.顯示圖片的cell,通過block回調把圖片傳到Controller中,用于放大圖片使用。

 1 #import "MyImageCell.h" 2  3 @interface MyImageCell() 4 @property (strong, nonatomic) IBOutlet UIImageView *bgImageView; 5 @property (strong, nonatomic) IBOutlet UIButton *imageButton; 6 @property (strong, nonatomic) ButtonImageBlock imageBlock; 7 @property (strong, nonatomic) UIImage *buttonImage; 8  9 @end10 11 @implementation MyImageCell12 13 -(void)setCellValue:(UIImage *)sendImage14 {15     self.buttonImage = sendImage;16     UIImage *image = [UIImage imageNamed:@"chatto_bg_normal.png"];17     image = [image resizableImageWithCapInsets:(UIEdgeInsetsMake(image.size.height * 0.6, image.size.width * 0.4, image.size.height * 0.3, image.size.width * 0.4))];18     [self.bgImageView setImage:image];19     [self.imageButton setImage:sendImage forState:UIControlStateNormal];20 21 }22 23 -(void)setButtonImageBlock:(ButtonImageBlock)block24 {25     self.imageBlock = block;26 }27 28 - (IBAction)tapImageButton:(id)sender {29     self.imageBlock(self.buttonImage);30 }31 32 @end
View Code

    3.顯示錄音的cell,點擊cell上的button,播放對應的錄音,代碼如下:

 1 #import "VoiceCellTableViewCell.h" 2  3 @interface VoiceCellTableViewCell() 4  5 @property (strong, nonatomic) NSURL *playURL; 6 @property (strong, nonatomic) AVAudioPlayer *audioPlayer; 7  8 @end 9 10 @implementation VoiceCellTableViewCell11 12 -(void)setCellValue:(NSDictionary *)dic13 {14     _playURL = dic[@"body"][@"content"];15 }16 17 - (IBAction)tapVoiceButton:(id)sender {18     19     20     NSError *error = nil;21     AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:_playURL error:&error];22     if (error) {23         NSLog(@"播放錯誤:%@",[error description]);24     }25     self.audioPlayer = player;26     [self.audioPlayer play];27 }28 @end
View Code

 

  二,cell搞定后要實現我們的ChatController部分    

    1.ChatController.m中的延展和枚舉代碼如下:

 1 //枚舉Cell類型 2 typedef enum : NSUInteger { 3     SendText, 4     SendVoice, 5     SendImage 6 } MySendContentType; 7  8  9 //枚舉用戶類型10 typedef enum : NSUInteger {11     MySelf,12     MyFriend13 } UserType;14 15 @interface ChatViewController ()16 17 //工具欄18 @property (nonatomic,strong) ToolView *toolView;19 20 //音量圖片21 @property (strong, nonatomic) UIImageView *volumeImageView;22 23 //工具欄的高約束,用于當輸入文字過多時改變工具欄的約束24 @property (strong, nonatomic) NSLayoutConstraint *tooViewConstraintHeight;25 26 //存放所有的cell中的內容27 @property (strong, nonatomic) NSMutableArray *dataSource;28 29 //storyBoard上的控件30 @property (strong, nonatomic) IBOutlet UITableView *myTableView;31 32 //用戶類型33 @property (assign, nonatomic) UserType userType;34 35 //從相冊獲取圖片36 @property (strong, nonatomic) UIImagePickerController *imagePiceker;37 38 @end
View Code

    2.實現工具欄中的回調的代碼如下,通過Block,工具欄和ViewController交互,具體ToolView的Block實現,請參考上一篇博客(iOS開發之微信聊天工具欄的封裝),聊天工具欄使用代碼如下:

 1 //實現工具欄的回調 2 -(void)setToolViewBlock 3 { 4     __weak __block ChatViewController *copy_self = self; 5     //通過block回調接收到toolView中的text 6     [self.toolView setMyTextBlock:^(NSString *myText) { 7         NSLog(@"%@",myText); 8          9         [copy_self sendMessage:SendText Content:myText];10     }];11     12     13     //回調輸入框的contentSize,改變工具欄的高度14     [self.toolView setContentSizeBlock:^(CGSize contentSize) {15          [copy_self updateHeight:contentSize];16     }];17     18     19     //獲取錄音聲量,用于聲音音量的提示20     [self.toolView setAudioVolumeBlock:^(CGFloat volume) {21         22         copy_self.volumeImageView.hidden = NO;23         int index = (int)(volume*100)%6+1;24         [copy_self.volumeImageView setImage:[UIImage imageNamed:[NSString stringWithFormat:@"record_animate_%02d.png",index]]];25     }];26     27     //獲取錄音地址(用于錄音播放方法)28     [self.toolView setAudioURLBlock:^(NSURL *audioURL) {29         copy_self.volumeImageView.hidden = YES;30         31         [copy_self sendMessage:SendVoice Content:audioURL];32     }];33     34     //錄音取消(錄音取消后,把音量圖片進行隱藏)35     [self.toolView setCancelRecordBlock:^(int flag) {36         if (flag == 1) {37             copy_self.volumeImageView.hidden = YES;38         }39     }];40     41     42     //擴展功能回調43     [self.toolView setExtendFunctionBlock:^(int buttonTag) {44         switch (buttonTag) {45             case 1:46                 //從相冊獲取47                 [copy_self presentViewController:copy_self.imagePiceker animated:YES completion:^{48                     49                 }];50                 break;51             case 2:52                 //拍照53                 break;54                 55             default:56                 break;57         }58     }];59 }
View Code

    3.把聊天工具欄中返回的內容顯示在tableView中,代碼如下:

 1 //發送消息 2 -(void)sendMessage:(MySendContentType) sendType Content:(id)content 3 { 4      5     //把收到的url封裝成字典 6     UserType userType = self.userType; 7      8     NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:2]; 9     [tempDic setValue:@(userType) forKey:@"userType"];10     11     NSDictionary *bodyDic = @{@"type":@(sendType),12                               @"content":content};13     [tempDic setValue:bodyDic forKey:@"body"];14     [self.dataSource addObject:tempDic];15     16     //重載tableView17     [self.myTableView  reloadData];18     19     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataSource.count-1 inSection:0];20     21     [self.myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];22     23  24 }
View Code

    4.根據ToolView中回調接口,獲取工具欄中textView的ContentSize,通過ContentSize來調整ToolView的高度約束,代碼如下:

 1 //更新toolView的高度約束 2 -(void)updateHeight:(CGSize)contentSize 3 { 4     float height = contentSize.height + 18; 5     if (height <= 80) { 6         [self.view removeConstraint:self.tooViewConstraintHeight]; 7          8         NSString *string = [NSString stringWithFormat:@"V:[_toolView(%f)]", height]; 9         10         NSArray * tooViewConstraintV = [NSLayoutConstraint constraintsWithVisualFormat:string options:0 metrics:0 views:NSDictionaryOfVariableBindings(_toolView)];11         self.tooViewConstraintHeight = tooViewConstraintV[0];12         [self.view addConstraint:self.tooViewConstraintHeight];13     }14 }
View Code

    5.從本地獲取圖片,并顯示在相應的Cell上,代碼如下:

 1 //獲取圖片后要做的方法 2 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 3 { 4     UIImage *pickerImage = info[UIImagePickerControllerEditedImage]; 5      6     //發送圖片 7     [self sendMessage:SendImage Content:pickerImage]; 8      9     [self dismissViewControllerAnimated:YES completion:^{}];10     11 }12 13 -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker14 {15     //在ImagePickerView中點擊取消時回到原來的界面16     [self dismissViewControllerAnimated:YES completion:^{}];17 }
View Code

    6.把NSString 轉換成NSMutableAttributeString,用于顯示表情,代碼如下:

 1 //顯示表情,用屬性字符串顯示表情 2 -(NSMutableAttributedString *)showFace:(NSString *)str 3 { 4     //加載plist文件中的數據 5     NSBundle *bundle = [NSBundle mainBundle]; 6     //尋找資源的路徑 7     NSString *path = [bundle pathForResource:@"emoticons" ofType:@"plist"]; 8     //獲取plist中的數據 9     NSArray *face = [[NSArray alloc] initWithContentsOfFile:path];10     11     //創建一個可變的屬性字符串12     13     NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:str];14     15     UIFont *baseFont = [UIFont systemFontOfSize:17];16     [attributeString addAttribute:NSFontAttributeName value:baseFont17                        range:NSMakeRange(0, str.length)];18     19     //正則匹配要替換的文字的范圍20     //正則表達式21     NSString * pattern = @"//[[a-zA-Z0-9//u4e00-//u9fa5]+//]";22     NSError *error = nil;23     NSRegularExpression * re = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];24     25     if (!re) {26         NSLog(@"%@", [error localizedDescription]);27     }28     29     //通過正則表達式來匹配字符串30     NSArray *resultArray = [re matchesInString:str options:0 range:NSMakeRange(0, str.length)];31     32     33     //用來存放字典,字典中存儲的是圖片和圖片對應的位置34     NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];35     36     //根據匹配范圍來用圖片進行相應的替換37     for(NSTextCheckingResult *match in resultArray) {38         //獲取數組元素中得到range39         NSRange range = [match range];40         41         //獲取原字符串中對應的值42         NSString *subStr = [str substringWithRange:range];43         44         for (int i = 0; i < face.count; i ++)45         {46             if ([face[i][@"chs"] isEqualToString:subStr])47             {48                 49                 //face[i][@"gif"]就是我們要加載的圖片50                 //新建文字附件來存放我們的圖片51                 NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];52                 53                 //給附件添加圖片54                 textAttachment.image = [UIImage imageNamed:face[i][@"png"]];55                 56                 //把附件轉換成可變字符串,用于替換掉源字符串中的表情文字57                 NSAttributedString *imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];58                 59                 //把圖片和圖片對應的位置存入字典中60                 NSMutableDictionary *imageDic = [NSMutableDictionary dictionaryWithCapacity:2];61                 [imageDic setObject:imageStr forKey:@"image"];62                 [imageDic setObject:[NSValue valueWithRange:range] forKey:@"range"];63                 64                 //把字典存入數組中65                 [imageArray addObject:imageDic];66                 67             }68         }69     }70     71     //從后往前替換72     for (int i = imageArray.count -1; i >= 0; i--)73     {74         NSRange range;75         [imageArray[i][@"range"] getValue:&range];76         //進行替換77         [attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];78         79     }80     81     return  attributeString;82 }
View Code

    7.根據Cell顯示內容來調整Cell的高度,代碼如下:

 1 //調整cell的高度 2 -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 3 { 4      5     //根據文字計算cell的高度 6     if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendText)]) { 7         NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]]; 8          9         CGRect textBound = [contentText boundingRectWithSize:CGSizeMake(150, 1000) options:NSStringDrawingUsesLineFragmentOrigin context:nil];10         11         float height = textBound.size.height + 40;12         return height;13     }14     if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendVoice)])15     {16         return 73;17     }18     19     if ([self.dataSource[indexPath.row][@"body"][@"type"] isEqualToNumber:@(SendImage)])20     {21         return 125;22     }23     24     return 100;25  }
View Code

    8.根據cell內容和用戶類型,來選擇Cell,代碼如下:

 1 //設置cell 2 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 3 { 4     //根據類型選cell 5     MySendContentType contentType = [self.dataSource[indexPath.row][@"body"][@"type"] integerValue]; 6      7      8     if ([self.dataSource[indexPath.row][@"userType"]  isEqual: @(MyFriend)]) { 9         switch (contentType) {10             case SendText:11             {12                 TextCell *cell = [tableView dequeueReusableCellWithIdentifier:@"textCell" forIndexPath:indexPath];13                 NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]];14                 [cell setCellValue:contentText];15                 return cell;16             }17                 break;18                 19             case SendImage:20             {21                 heImageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"heImageCell" forIndexPath:indexPath];22                 [cell setCellValue:self.dataSource[indexPath.row][@"body"][@"content"]];23                 24                 25                 __weak __block ChatViewController *copy_self = self;26                 27                 //傳出cell中的圖片28                 [cell setButtonImageBlock:^(UIImage *image) {29                     [copy_self displaySendImage:image];30                 }];31                 return cell;32             }33                 break;34                 35             case SendVoice:36             {37                 VoiceCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"heVoiceCell" forIndexPath:indexPath];38                 [cell setCellValue:self.dataSource[indexPath.row]];39                 return cell;40             }41 42                 break;43                 44             default:45                 break;46         }47 48     }49         50 51     if ([self.dataSource[indexPath.row][@"userType"]  isEqual: @(MySelf)]) {52     53         switch (contentType) {54             case SendText:55             {56                 TextCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myselfTextCell" forIndexPath:indexPath];57                 NSMutableAttributedString *contentText = [self showFace:self.dataSource[indexPath.row][@"body"][@"content"]];58                 [cell setCellValue:contentText];59                 return cell;60             }61             break;62             63             case SendImage:64             {65                 MyImageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myImageCell" forIndexPath:indexPath];66                 [cell setCellValue:self.dataSource[indexPath.row][@"body"][@"content"]];67                 68                 __weak __block ChatViewController *copy_self = self;69                 70                 //傳出cell中的圖片71                 [cell setButtonImageBlock:^(UIImage *image) {72                     [copy_self displaySendImage:image];73                 }];74 75                 76                 return cell;77             }78                 break;79             80             case SendVoice:81             {82                 VoiceCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myVoiceCell" forIndexPath:indexPath];83                 [cell setCellValue:self.dataSource[indexPath.row]];84                 return cell;85             }86 87                 break;88                 89             default:90                 break;91         }92     }93     UITableViewCell *cell;94     return cell;95 }
View Code

    9.點擊發送的圖片來放大圖片代碼如下:

 1 //發送圖片的放大 2 -(void) displaySendImage : (UIImage *)image 3 { 4     //把照片傳到放大的controller中 5     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 6      7     ImageViewController *imageController = [storyboard instantiateViewControllerWithIdentifier:@"imageController"]; 8     [imageController setValue:image forKeyPath:@"image"]; 9     10    [self.navigationController pushViewController:imageController animated:YES];11     12 13 }
View Code

    10.根據鍵盤的高度來調整ToolView的位置,代碼如下:

 1 //鍵盤出來的時候調整tooView的位置 2 -(void) keyChange:(NSNotification *) notify 3 { 4     NSDictionary *dic = notify.userInfo; 5      6      7     CGRect endKey = [dic[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; 8     //坐標系的轉換 9     CGRect endKeySwap = [self.view convertRect:endKey fromView:self.view.window];10     //運動時間11     [UIView animateWithDuration:[dic[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{12         13         [UIView setAnimationCurve:[dic[UIKeyboardAnimationCurveUserInfoKey] doubleValue]];14         CGRect frame = self.view.frame;15         16         frame.size.height = endKeySwap.origin.y;17         18         self.view.frame = frame;19         [self.view layoutIfNeeded];20     }];21 }
View Code

 

  三,代碼有點多,不過在關鍵的部分都加有注釋,在圖片顯示View中通過捏合手勢來調整圖片的大小,代碼如下:

 1 - (IBAction)tapPichGesture:(id)sender { 2     UIPinchGestureRecognizer *gesture = sender; 3      4     //手勢改變時 5     if (gesture.state == UIGestureRecognizerStateChanged) 6     { 7          8         //捏合手勢中scale屬性記錄的縮放比例 9         self.myImageView.transform = CGAffineTransformMakeScale(gesture.scale, gesture.scale);10     }11     12 }
View Code

  

  上面的東西是在本地做的測試,沒有加上XMPP即時通訊協議,以后的博客會通過服務器轉發來進行聊天,并且會繼續對微信進行完善,感興趣的小伙伴繼續關注吧。轉載請注明出處。

  Demo地址:https://github.com/lizelu/WeChat


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 固原市| 湄潭县| 大荔县| 上犹县| 水城县| 稷山县| 吉木乃县| 香格里拉县| 攀枝花市| 黄梅县| 方城县| 桂东县| 方城县| 沁源县| 天气| 乐昌市| 余姚市| 从江县| 郎溪县| 达尔| 吕梁市| 通河县| 乐清市| 特克斯县| 徐州市| 奈曼旗| 景谷| 南木林县| 夏河县| 罗定市| 洞头县| 桂平市| 凌源市| 浪卡子县| 南雄市| 九龙坡区| 天气| 成都市| 庐江县| 彭泽县| 常熟市|