iOS IM即时通信之聊天界面UI框架

效果:

聊天效果.gif

随便扯扯

公司项目以前就集成环信, 后来不知道什么原因给撤了, 最近又不知道打什么鸡血要上IM, 界面一个礼拜搭建完成, 前前后后两个月一直在改pm, 改接口, 一把心酸一把泪, 由于后台拖拖拖, 产品改改改, 我的小儿子终于在前两个礼拜上线啦(≧≦)/啦啦啦,
最近闲的蛋疼, 决定把我的小儿子抽出来给大家玩玩, 里面也借鉴了很多优秀的代码, 喜欢的可以参考(写的比较简单, 勿喷~)

项目结构


项目结构.png
项目结构.png

表情键盘

  • 如何更改? 在下面的代码修改plist文件, 替换表情图片
+ (NSArray *)loadPackages {
    if (_packages) {
        return _packages;
    }

    NSMutableArray *models = [NSMutableArray array];
    KeyboardEmojiPackage *packge = [[KeyboardEmojiPackage alloc] init];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"emoticons.plist" ofType:nil];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
    NSArray *array = dict[@"packages"];

    for (NSDictionary *dict in array) {
        KeyboardEmojiPackage *package = [[KeyboardEmojiPackage alloc] initWithDict:dict];
        [packge loadEmojis];
        [packge appendEmptyEmoji];
        [models addObject:package];
    }

    _packages = models;
    return models;
}


/**
 *  加载当前组所有的表情
 */
- (void)loadEmojis {

    NSString *path = [[NSBundle mainBundle] pathForResource:self.group_name ofType:nil];

    NSArray *array = [NSArray arrayWithContentsOfFile:path];

    NSMutableArray *models = [NSMutableArray array];

    NSInteger index = 0;

    for (NSDictionary *dict in array) {
        KeyboardEmojiModel *emotion = [[KeyboardEmojiModel alloc] initWithDict:dict];
        emotion.group_folder_name = self.group_folder_name;
        [models addObject:emotion];
        index ++;
    }

    self.emojis = models;
}
  • 修改布局
    • 根据需要修改3 X 7 或 2 X 4
- (void)prepareLayout {
    CGFloat itemWith = [UIScreen mainScreen].bounds.size.width / 4;
    CGFloat itemHeight = 55;
    self.itemSize = CGSizeMake(itemWith, itemHeight);
    self.minimumLineSpacing = 0;
    self.minimumInteritemSpacing = 0;
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    self.collectionView.pagingEnabled = YES;
    self.collectionView.showsVerticalScrollIndicator = NO;
    self.collectionView.showsHorizontalScrollIndicator = NO;
//    self.collectionView.bounces = NO;

    // 让cell居中显示
    CGFloat offsetY = (self.collectionView.bounds.size.height - (2 * itemHeight)) * 0.48;
    self.collectionView.contentInset = UIEdgeInsetsMake(offsetY, 0, 0, offsetY);
}
  • 聊天气泡

    聊天气泡用的是图片, 用户可自定义更换

// bubbleView 的背景图片
NSString *const BUBBLE_LEFT_IMAGE_NAME = @"IM_Chat_receiver_bg";
NSString *const BUBBLE_RIGHT_IMAGE_NAME = @"IM_Chat_sender_bg";

说一下输入框的问题

输入框用的是textView, 在输入框换行改变高度到第二行的时候, 文字会向上偏移, 到第三行又正常, 回退也是正常的, 这个问题纠结的很久, 也查了很多资料, 如果有朋友遇到这个问题可以借鉴下面的代码

#pragma mark - UITextViewDelegate
- (void)textViewDidChange:(UITextView *)textView {

   static CGFloat maxHeight = 80.0f;
   CGRect frame = textView.frame;
   CGSize constraintSize = CGSizeMake(frame.size.width, MAXFLOAT);
   CGSize size = [textView sizeThatFits:constraintSize];
   if (size.height >= maxHeight) {
       size.height = maxHeight;
       textView.scrollEnabled = YES;   // 允许滚动
       [textView scrollRectToVisible:CGRectMake(0, textView.contentSize.height-7.5, textView.contentSize.width, 10) animated:NO];
   } else {
       textView.scrollEnabled = NO;    // 不允许滚动,当textview的大小足以容纳它的text的时候,需要设置scrollEnabed为NO,否则会出现光标乱滚动的情况
   }

   [UIView animateWithDuration:_animationDuration delay:0 options:(_animationCurve << 16 | UIViewAnimationOptionBeginFromCurrentState) animations:^{
       // 调整整个InputToolBar 的高度
       self.height = (15 + size.height) - kChatBarHeight < 5 ? kChatBarHeight : 15 + size.height;
       CGFloat keyboardHeight = _keyboardHeight;
       if (self.moreBtn.selected) {
           keyboardHeight = kChatMoreHeight;
       }
       else if (self.emojiBtn.selected) {
           keyboardHeight = kChatEmojiHeight;
       }

       self.y = SCREEN_H - self.height - keyboardHeight;
       _tableView.height = self.y - kNavBarHeight;
       [self layoutIfNeeded];
   } completion:nil];
}

第三方开源框架

FMDB --> 对SQLite的API进行了封装
SDWebImage --> 缓存下载图片
TZImagePickerController --> 一个支持多选、选原图和视频的图片选择器,同时有预览、裁剪功能
YYKit --> 是一组庞大、功能丰富的 iOS 组件

写在最后

整个消息UI还是仿照环信的, 基本上大致相同, 只是稍加修改, 因为需求只需要聊天, 文字, 表情, 所以demo也只有这些, 基本比较简单, 如果觉得本文对你有帮助,感谢给个star
github地址:LHChat

补充一下

聊天cell里面也能显示动图,但是发送大量动态表情的时候,滑动是会卡顿,用yylabel开启异步绘制还是一样,研究了挺久的,也琢磨不出来什么,有知道的大神还望在留言区指点一下,给个思路也行,谢谢(๑ᴖᴖ๑)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容