上篇博客介绍了如何使用UITableView实现类似QQ的好友界面布局。这篇讲述如何利用自定义单元格来实现聊天界面的布局。

借助单元格实现聊天布局难度不大,主要要解决的问题有两个:

1.自己和其他人说话头像和气泡图像在不同的位置。

找了些类似的例子,有根据不同情况设置不同的自定义类的。这里使用根据说话人的属性来设置不同的位置,在一个单一的单元格类中。

2.像微博等根据说话的内容长短对说话图片进行拉伸,以及单元格自适应高度。

实现步骤:

搭建界面

数据属性字典

读取数据

- (void)loadData
{
const NSString *RMsgKey = @"msg";
const NSString *RMineKey = @"ismine"; NSString *path = [[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"];
NSArray *dataArray = [NSArray arrayWithContentsOfFile:path];
if (!dataArray)
{
MyLog(@"读取文件失败");
return;
} _msgList = [NSMutableArray arrayWithCapacity:dataArray.count];
[dataArray enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
Message *message = [[Message alloc] init];
message.msg = dict[RMsgKey];
message.mine = [dict[RMineKey] boolValue];
[_msgList addObject:message];
}];
}

将数据指定给Message类,存到一个数组中方便以后绑定到自定义单元格中

这次使用的是用NIB文件建的自定义,而非像前两篇博客使用手绘的方式。

awakeFromNib和layoutSubviews方法

- (void)awakeFromNib
{
_msgButton.titleLabel.numberOfLines = 0;
_msgButton.titleLabel.font = [UIFont systemFontOfSize:RChatFontSize];
} - (void)layoutSubviews
{
[super layoutSubviews]; CGRect rect = _msgButton.frame;
rect.size.height = self.bounds.size.height - 2*RMarginSize;
_msgButton.frame = rect;
}

然后是数据绑定方法,根据传入的数据,安排头像和会话按钮的位置

- (void)bindMessage:(Message *)message
{
UIImage *headerImage;
UIImage *normalImage;
UIImage *highlightedImage; CGRect iconRect = _headerView.frame;
CGRect btnRect = _msgButton.frame; UIEdgeInsets insets; if (message.isMine)
{
headerImage = [UIImage imageNamed:@"me"];
normalImage = [UIImage imageNamed:@"mychat_normal"];
highlightedImage = [UIImage imageNamed:@"mychat_focused"]; iconRect.origin.x = RMarginSize;
btnRect.origin.x = RBtnX; insets = UIEdgeInsetsMake(0, 20, 0, 30);
}
else
{
headerImage = [UIImage imageNamed:@"other"];
normalImage = [UIImage imageNamed:@"other_normal"];
highlightedImage = [UIImage imageNamed:@"other_focused"]; iconRect.origin.x = self.bounds.size.width - RMarginSize - RIconSide;
btnRect.origin.x = self.bounds.size.width - iconRect.origin.x - RMarginSize; insets = UIEdgeInsetsMake(0, 30, 0, 30);
}
_headerView.frame = iconRect;
_headerView.image = headerImage; //拉伸图片
normalImage = [normalImage stretchableImageWithLeftCapWidth:normalImage.size.width*0.5 topCapHeight:normalImage.size.height*0.6];
highlightedImage = [highlightedImage stretchableImageWithLeftCapWidth:highlightedImage.size.width*0.5 topCapHeight:highlightedImage.size.height*0.6]; [_msgButton setContentEdgeInsets:insets];
_msgButton.frame = btnRect;
[_msgButton setBackgroundImage:normalImage forState:UIControlStateNormal];
[_msgButton setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];
[_msgButton setTitle:message.msg forState:UIControlStateNormal];
}

关于上面拉伸图片的方法,在IOS6以后可以使用另一个方法,resizableImageWithCapInsets:<#(UIEdgeInsets)#> resizingMode:<#(UIImageResizingMode)#>

传入一个Edgeinsets和一个拉伸模式就可以对图片完成编辑。

下面在tableview的代理方法中设置自适应高度的行高

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
Message *msg = _msgList[indexPath.row];
UIFont *font = [UIFont systemFontOfSize:RChatFontSize];
CGFloat height = [msg.msg sizeWithFont:font constrainedToSize:CGSizeMake(150, 10000)].height;
CGFloat lineHeight = [font lineHeight]; return RCellHeight + height - lineHeight;
}

根据内容和字体设置合适的高度

最后绑定数据就可以完成显示了

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HRChatCell *cell = [tableView dequeueReusableCellWithIdentifier:RCellIdentifier];
[cell bindMessage:_msgList[indexPath.row]];
return cell;
}

完成效果

Demo源码:点击打开链接

以上为本篇博客全部内容,欢迎指正和交流。转载请注明出处~

IOS详解TableView——对话聊天布局的实现的更多相关文章

  1. IOS详解TableView——选项抽屉(天猫商品列表)

    在之前的有篇文章讲述了利用HeaderView来写类似QQ好友列表的表视图. 这里写的天猫抽屉其实也可以用该方法实现,具体到细节每个人也有所不同.这里采用的是点击cell对cell进行运动处理以展开“ ...

  2. IOS详解TableView——内置刷新,EGO,以及搜索显示控制器

    内置刷新 内置刷新是苹果IOS6以后才推出的一个API,主要是针对TableViewController增加了一个属性,refreshControl,所以如果想用这个内置下拉刷新的话,最好给你的Tab ...

  3. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  4. iOS:详解MJRefresh刷新加载更多数据的第三方库

    原文链接:http://www.ios122.com/2015/08/mjrefresh/ 简介 MJRefresh这个第三方库是李明杰老师的杰作,这个框架帮助我们程序员减轻了超级多的麻烦,节约了开发 ...

  5. Xamarin+Prism开发详解五:页面布局基础知识

    说实在的研究Xamarin到现在,自己就没设计出一款好的UI,基本都在研究后台逻辑之类的!作为Xamarin爱好者,一些简单的页面布局知识还是必备的. 布局常见标签: StackLayout Abso ...

  6. QDockWidget嵌套布局详解-实现Visual Studio布局

    概述 许多工程软件,如Qt Creator,VS,matlab等,都是使用dock布局窗口,这样用户可以自定义界面,自由组合窗口. Qt的嵌套布局由QDockWidget完成,用Qt Creator拖 ...

  7. [iOS]详解调整UIButton的title和image的位置

    UIButton的默认布局是:title在右,image在左; 很多时候我们需要的是title在左边,或者title在下面,这时就需要调整UIButton的TitleLabel和ImageView的位 ...

  8. 详解CSS的Flex布局

    本文由云+社区发表 Flex是Flexible Box 的缩写,意为"弹性布局",是CSS3的一种布局模式.通过Flex布局,可以很优雅地解决很多CSS布局的问题.下面会分别介绍容 ...

  9. Android五大布局详解——TableLayout(表格布局)

    TableLayout 前面所学的LinearLayout和RelativeLayout两大布局已经完全适用于各种开发条件下,其他的布局仅供参考学习,毕竟知识就是力量,以后的开发过程中万一遇到也能游刃 ...

随机推荐

  1. ShareSDK for Android 只有新浪微博分享

    本文代码例子:http://pan.baidu.com/share/link?shareid=3710053477&uk=3189484501 ShareSDK 官方的例子非常好,但代码太多看 ...

  2. 【转】linux挂载新硬盘,开机自动挂载

    [转]linux挂载新硬盘,开机自动挂载 ※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※ Linux的硬盘识别: 2.6 kernel以后,linux会将 ...

  3. MFC工程的复制

    MFC工程的复制 [1]       在VS中新建一个同类型的MFC工程. [2]       复制.rc资源文件,用记事本打开旧工程和新工程的.rc文件,将旧工程的对应部分复制到新工程的对应部分,文 ...

  4. 深入理解GCD ( 二 )

    转自@nixzhu的GitHub主页(译者:Riven.@nixzhu),原文<Grand Central Dispatch In-Depth: Part 2/2> 欢迎来到GCD深入理解 ...

  5. php四舍五入函数(floor、ceil、round与intval)

    原文链接:php四舍五入函数(floor.ceil.round与intval) PHP(外文名: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言.语法 ...

  6. jquery倒计时自动跳转

    刚开始我用下面这种方法一直报错,不知是什么原因,就是多加了页面加载时调用这个方法,还请高手看到后小小留言解惑

  7. 浙江工商大学15年校赛I题 Inversion 【归并排序求逆序对】

    Inversion Time Limit 1s Memory Limit 131072KB Judge Program Standard Ratio(Solve/Submit) 15.00%(3/20 ...

  8. POJ 1379 Run Away 【基础模拟退火】

    题意:找出一点,距离所有所有点的最短距离最大 二维平面内模拟退火即可,同样这题用最小圆覆盖也是可以的. Source Code: //#pragma comment(linker, "/ST ...

  9. thinkphp 分组、页面跳转与ajax

    本节课大纲: 一.多应用配置技巧 二.使用分组 三.页面跳转 $this->success('查询成功',U('User/test')); $this->redirect('User/te ...

  10. CString 操作指南

    过阅读本文你可以学习如何有效地使用 CString. CString 是一种很有用的数据类型.它们很大程度上简化了MFC中的许多操作,使得MFC在做字符串操作的时候方便了很多.不管怎样,使用CStri ...