這篇文章主要介紹iOS開發(fā)之微信聊天頁面怎么實現(xiàn) ,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
成都創(chuàng)新互聯(lián)是一家專業(yè)提供雙城企業(yè)網(wǎng)站建設,專注與網(wǎng)站建設、成都網(wǎng)站建設、HTML5、小程序制作等業(yè)務。10年已為雙城眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡公司優(yōu)惠進行中。聊天界面的效果圖如下:在下面的聊天界面中中用到了3類cell,一類是顯示文字和表情的,一類是顯示錄音的,一類是顯示圖片的。當點擊圖片時會跳轉到另一個Controller中來進行圖片顯示,在圖片顯示頁面中添加了一個捏合的手勢。點擊播放按鈕,會播放錄制的音頻,cell的大學會根據(jù)內(nèi)容的多少來調(diào)整,而cell中textView的高度是通過約束來設置的。

一,定義我們要用的cell,代碼如下:
1,顯示表情和text的cell,代碼如下,需要根據(jù)NSMutableAttributedString求出bound,然后改變cell上的ImageView和TextView的寬度的約束值,動態(tài)的調(diào)整氣泡的大小,具體代碼如下:
#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];
//根據(jù)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;
}
@end2.顯示圖片的cell,通過block回調(diào)把圖片傳到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);
}
@end3.顯示錄音的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搞定后要實現(xiàn)我們的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中的內(nèi)容
@property (strong, nonatomic) NSMutableArray *dataSource;
//storyBoard上的控件
@property (strong, nonatomic) IBOutlet UITableView *myTableView;
//用戶類型
@property (assign, nonatomic) UserType userType;
//從相冊獲取圖片
@property (strong, nonatomic) UIImagePickerController *imagePiceker;
@end實現(xiàn)工具欄中的回調(diào)的代碼如下,通過Block,工具欄和ViewController交互
//實現(xiàn)工具欄的回調(diào)
-(void)setToolViewBlock
{
__weak __block ChatViewController *copy_self = self;
//通過block回調(diào)接收到toolView中的text
[self.toolView setMyTextBlock:^(NSString *myText) {
NSLog(@"%@",myText);
[copy_self sendMessage:SendText Content:myText];
}];
//回調(diào)輸入框的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;
}
}];
//擴展功能回調(diào)
[self.toolView setExtendFunctionBlock:^(int buttonTag) {
switch (buttonTag) {
case 1:
//從相冊獲取
[copy_self presentViewController:copy_self.imagePiceker animated:YES completion:^{
}];
break;
case 2:
//拍照
break;
default:
break;
}
}];
}把聊天工具欄中返回的內(nèi)容顯示在tableView中,代碼如下:
//發(fā)送消息
-(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];
}根據(jù)ToolView中回調(diào)接口,獲取工具欄中textView的ContentSize,通過ContentSize來調(diào)整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];
//發(fā)送圖片
[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文件中的數(shù)據(jù)
NSBundle *bundle = [NSBundle mainBundle];
//尋找資源的路徑
NSString *path = [bundle pathForResource:@"emoticons" ofType:@"plist"];
//獲取plist中的數(shù)據(jù)
NSArray *face = [[NSArray alloc] initWithContentsOfFile:path];
//創(chuàng)建一個可變的屬性字符串
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];
//根據(jù)匹配范圍來用圖片進行相應的替換
for(NSTextCheckingResult *match in resultArray) {
//獲取數(shù)組元素中得到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"];
//把字典存入數(shù)組中
[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;
}根據(jù)Cell顯示內(nèi)容來調(diào)整Cell的高度,代碼如下:
//調(diào)整cell的高度
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//根據(jù)文字計算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;
}根據(jù)cell內(nèi)容和用戶類型,來選擇Cell,代碼如下:
//設置cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//根據(jù)類型選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;
}點擊發(fā)送的圖片來放大圖片代碼如下:
//發(fā)送圖片的放大
-(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];
}根據(jù)鍵盤的高度來調(diào)整ToolView的位置,代碼如下:
//鍵盤出來的時候調(diào)整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中通過捏合手勢來調(diào)整圖片的大小,代碼如下:
- (IBAction)tapPichGesture:(id)sender {
UIPinchGestureRecognizer *gesture = sender;
//手勢改變時
if (gesture.state == UIGestureRecognizerStateChanged)
{
//捏合手勢中scale屬性記錄的縮放比例
self.myImageView.transform = CGAffineTransformMakeScale(gesture.scale, gesture.scale);
}
}以上是“iOS開發(fā)之微信聊天頁面怎么實現(xiàn) ”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
當前名稱:iOS開發(fā)之微信聊天頁面怎么實現(xiàn)-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://chinadenli.net/article24/ccgsce.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供響應式網(wǎng)站、企業(yè)建站、服務器托管、網(wǎng)站設計公司、靜態(tài)網(wǎng)站、移動網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)