ios cell嵌套webviewtableviewcell 回调 怎么有cell的row

IOS 如何动态设置每个TableViewCell的高度?
我怎么动态设置UITableView的Cell的高度,在我的TableViewCell里面有加载网络的图片,但每个图片的高度都是不一样的, &开始的时候,我加载了一张默认的图片,设置了CELL的高度,但当我异步加载了真正图片之后 ,这个时候怎么去调整每个Cell的高度
发帖于&3年前
回/11646阅
共有6个答案
加载完图片之后,调用
[tableView beginUpdate]
[tableView endUpdate]
之后tableView就会再次调用heightForRowAtIndexPath,这时候你就可以返回正确的cell高度给它了。
--- 共有 5 条评论 ---
: 直接在当前tableview里获取数据,进行修改
: 求分享解决办法
我已经解决了,不用这种方法。。。
我用你这种方法加载完webview然后返回到tableview去算cgfloat是ok的,
但我又用这个方法去在我自定义的cell里算完cell高度后,返还到tableview去改变cgfloat就不行了,为什么啊???
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 方法
--- 共有 2 条评论 ---
: 看下我说的方法,不过估计你早都实现了。。。
这个方法是在加载TableViewCell的时候先执行的,我现在是开始的时候在你说的那个方法里面设置了高度,然后异步 加载图片,加载过来的图片的高度可能 不一样,这时候怎么重新设置这个Cell的高度
&首先创建一个方法,计算出要加载的东西的高度然后将高度传到上面的方法中
你会有这个问题是因为你把数据加载的过程让Cell去做了。Cell只是一个View,它的所有行为都是Controller来控制的。Cell只负责根据传进来的数据进行显示。数据的加载都在Controller里做完,然后reloadData。一切自动就好了。
有一种解决办法是这样的:
设置一个专门管理cell高度的字典,用indexPath.row作为KEY,Value初始化为44。比如名字叫heightDict
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
在这个方法中,indexPath.row作为key,从heightDict中拿到Value。这个value就是返回值。
Cell中,每次下载更新图片前,先把cell高度保存起来。等下载更新完成,界面重新设置完毕后,比较当前cell高度和保存值是否相同。如果不同,就发delegate给ViewController,把当前cell高度和indexpath当作参数传递出去。
ViewController中的delegate回调方法中,把indexPath.row作为key,将传入的Cell高度存入heightDict中,然后[tableView reloadData]
在 heightforrowatindexpath里动态处理 cell 高度
馆藏&22124
TA的最新馆藏iOS中tableView和自定义tableViewCell的使用方法总结 - 简书
iOS中tableView和自定义tableViewCell的使用方法总结
本文的重点并不仅是UITableView的基本使用方法,而是强调有关UITableView和UITableViewCell开发过程中的一些具体细节问题。基本信息请参阅Apple开发文档。
Table可能是最擅长于展示数据的一种UI部件。因此UITableView这个类是iOS App开发中除button和Label之外最常用的控件类型。几乎任何一个App都离不开tableView。使用UITableView很简单,核心就是要实现两个protocol。这是由于tableView在MVC中只是V这一环,所以它需要额外的支持提供另外的MC两个环节的功能才能让一个table完整的工作。而这种支持实现的途径就是protocol,Apple要求开发者提供实现 UITableViewDataSource 和UITableViewDelegate 这两个protocol的支持类来协同对应的UITableView的工作。一般情况下,实现delegate protocol的类是UITableViewController,而data source protocol 可以是controller负责,也可以是其他helper类完成。但更多情况下,我更倾向于单独的modal wrapper类来完成。现在很多的建议data source尽可能不要放在controller中,这样有利于解决mass controller的问题。可以参考objc.io这篇文章:
鉴于UITableView是如此的重要,iOS替我们定制化了两种类型的tableView:static和dynamic。前者适用于表格内容相对固定的场景,更多的使用在诸如Setting panel,Detail panel的地方;而后者适用于表格内容不固定,行数动态变化的场景,更多的使用在网络请求返回后,将动态的数据进行内容展示等。虽然Apple内置了几种(确切的说到目前为止是4种)table的style,但是对于App开发而言,大多数情况下都需要自行定制table对数据的展示方式,因此相对应的,table cell的定制化成为App开发的必修课题。
那么下文将介绍一下Static table的使用中需要注意的一些地方和dynamic table中cell开发的方法总结。
关于Static Table的报错
static table的设置方法很简单,在Xcode中设置UITableView的类型为static即可。这里着重强调一个问题,绝大多数使用static table view的人都会遇到xcode报出的一个莫名其妙的错误:
而这个问题的原因是:放置static table的View Controller
必须为iOS内置的UITableViewController类型
据说这是xcode的一个bug,但是到目前为止还没有被“修复”的迹象,总而言之,造成的结果就是,如果你想在某个页面放置一个static table view,你必须单独放在UITableViewController中,而且仅仅手动将自己的viewController的类继承自UITableViewController或者在xib中强制改成UITableViewController都不行,必须是原生的UITableViewController。可是很多情况下我们确实需要在自己的viewcontroller中添加一个static table view。怎么办?解决方法是使用Container View。
在你自己的ViewController中拖入一个Container View
删除这个Container View自动创建的segue和对应的target view controller
containerView.png
拖入一个新的UITableViewController,加入一个table view,修改类型为static;
Ctrl-drag container view到这个UITableViewController,在弹出的segue类型中选择Embed:
statictable.gif
当然,这种方式只适用于storyboard操作并且要求支持Container VC的iOS版本。在其他情况下,可以直接使用addSubView:,将UITableViewController的view(当然就是tableView)加到自己的“container”view之下。
UITableViewCell的使用方法
下文的重点是总结UITableView和UITableViewCell的核心方法。更多详情可以参考Apple的官方文档。
1. 预定义Cell
iOS自定义了4种常见的Cell格式,在UITableViewCell.h中的注释中Apple给了一些明确的提示这些预置的style一般都适用于什么场景:
typedef enum {
UITableViewCellStyleDefault,
// Simple cell with text label and optional image view (behavior of UITableViewCell in iPhoneOS 2.x)
UITableViewCellStyleValue1,
// Left aligned label on left and right aligned label on right with blue text (Used in Settings)
UITableViewCellStyleValue2,
// Right aligned label on left with blue text and left aligned label on right (Used in Phone/Contacts)
UITableViewCellStyleSubtitle
// Left aligned label on top and left aligned label on bottom with gray text (Used in iPod).
} UITableViewCellStyle
4种类型在Xcode中对应的选项为:Basic, Right Detail, Left Detail和Subtitle。在iOS8下测试,对应的示例图如下:
Right Detail有图时:
rightdetail1.png
Right Detail无图时:
rightdetail2.png
Left Detail:
leftdetail.png
Subtitle:
subtitle.png
在这4种格式都统一有3个property可以供你使用:
textLabel:一个主标题
detailTextLabel:一个副标题
imageView:一张详情缩略图片
实际上这些预置类型就是把这3种元素做了些取舍然后在不同的位置组合了一下。我觉得在设计App的时候,在任何情况下,设计师和工程师都应当首先考虑这些预置的类型能不能满足需求,除非有足够的必要,否则不要轻易的浪费经历在重复构造定制化的View上。个人觉得Subtile模式已经适用于绝大多数对UI要求不高的场合。你完全可以自己修改这3个控件的一些属性来对UI进行微调。比如你可以尝试将imageView的大小放大一些。
2. 自定义Cell
UITableView是通过调用UITableViewDataSource中的tableView:cellForRowAtIndexPath:方法来获取每一行所需要的Cell的,所以绝大多自定义Cell的处理过程都是在这一步完成,另外由于UITableViewCell本身也是一个UIView,所以你也可以在UITableViewDelegate中的tableView:willDisplayCell:forRowAtIndexPath: 方法中对Cell的view做最后的定制化。
注意: Apple明确指出,在tableView:willDisplayCell:forRowAtIndexPath:中应当只修改“state-based properties”,比如selection和background color等等,但是不应该是内容(content),也就是不要在这里进行任何数据处理。
2.1 自定义Cell的创建
有以下几种方法:
方法1:使用Code继承预定义的cell样式,然后再手动添加自己的view
这是Apple官方文档中的示例,它通过调用initWithStyle:reuseIdentifier:使用UITableViewCellStyleDefault参数来创建一个Cell,为了方便期间,我对代码稍做了些改动,一个是简化了数据加载,另一个是用NSTextAlignment替换了废弃的UITextAlignment:
#define MAINLABEL_TAG 1
#define SECONDLABEL_TAG 2
#define PHOTO_TAG 3
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"ImageOnRightCell";
static int i = 0;
UILabel *mainLabel, *secondL
UIImageView *
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureB
mainLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 220.0, 15.0)];
mainLabel.tag = MAINLABEL_TAG;
mainLabel.font = [UIFont systemFontOfSize:14.0];
mainLabel.textAlignment = NSTextAlignmentR
mainLabel.textColor = [UIColor blackColor];
mainLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleH
[cell.contentView addSubview:mainLabel];
secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 20.0, 220.0, 25.0)];
secondLabel.tag = SECONDLABEL_TAG;
secondLabel.font = [UIFont systemFontOfSize:12.0];
secondLabel.textAlignment = NSTextAlignmentR
secondLabel.textColor = [UIColor darkGrayColor];
secondLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleH
[cell.contentView addSubview:secondLabel];
photo = [[UIImageView alloc] initWithFrame:CGRectMake(225.0, 0.0, 80.0, 45.0)];
photo.tag = PHOTO_TAG;
photo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleH
[cell.contentView addSubview:photo];
mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
secondLabel = (UILabel *)[cell.contentView viewWithTag:SECONDLABEL_TAG];
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
mainLabel.text = [NSString stringWithFormat:@"Title_%d", i];
secondLabel.text = [NSString stringWithFormat:@"Description_%d", i];
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"];
photo.image = theI
最终效果如下:
CustomCell1.png
这里有两个重点:
1) Cell的重用机制重用机制对于UITableView而言是非常重要的概念,这能够显著提高滑动TableView时的性能。如果不使用重用,那么每次新的Cell出现在屏幕上时都需要新创建一个,这对快速滑动而言是非常影响用户体验,并且会占用系统大量的内存开销。iOS的TableView使用的重用机制在原理上很简单,就是系统自动维护一个queue,这个队列放着一定数量的准备好的Cell UI object,滑出屏幕范围之外一定“距离”的Cell都会被回收到这个queue里,给马上要滑入屏幕范围内的Cell复用。使用重用的方法核心是两个概念:Cell Identity和dequeue。前者是标识一种具体的Cell的id,后者是将Cell从复用队列中取出的实际操作。首先你需要用这个id告诉系统你将要用于重用的Cell是谁(注册),然后你使用这个id从重用的队列里取出来(复用)。具体到本例中的API就是如下两个:initWithStyle:reuseIdentifier:和dequeueReusableCellWithIdentifier:。后面将看到,对于不同情况下创建的Cell,注册和复用的调用也并不相同。
2) 必须把自定义的控件添加在cell的contentView上,而不是view上,也就是:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// Correct!
[cell.contentView addSubview:yourCustomComponetView];
// [cell.view addSubview:yourCustomComponentView];
再次强调一点,Cell的Content View不是自己的root view。关于Cell View的结构可以参考这篇文章:这里只摘出最终结论,能够让你对一个Cell的view有直观的理解。对于一个如图所示的Table而言:
sample.png
它的TableViewCell的View层级结构是:
&UITableViewC frame = (0 396; 320 44);& //1
| &UITableViewCellScrollV frame = (0 0; 320 44); & //2
| &UIB frame = (302 16; 8 12.5)& //3
| &UIImageV frame = (0 0; 8 12.5);& //4
| &UITableViewCellContentV frame = (0 0; 287 44);& //5
| &UIL frame = (15 0; 270 43);& //6
这个Cell 里有六个视图:
* UITableViewCell 这是最高层的视图。 Frame 显示它有 320 点宽和 44 点高——宽度和高度都和预期的一致,因为它和屏幕一样宽,而高度就是 44 点。
* UITableViewCellScrollView 虽然你不能直接使用这个私有类,但它的名字很好地暗示了它的功能。它的 Size 和 Cell 的一样。
* UIButton 它在 Cell 的最右边,就是 Disclosure Indicator 按钮。
* UIImageView 是上面 UIButton 的子视图,装载着 Disclosure Indicator 的图像。
* UITableViewCellContentView 另外一个私有类,它包含 Cell 的内容。这个类对于开发者来说就是 UITableViewCell 的 contentView 属性。但它只作为一个 UIView 来暴露在外,这就意味着你只在其上调用使用公开的 UIView 方法;而不能使用任何与这个类关联的任何私有方法。
* UILabel 显示 “Item #” 文本。
很显然,这里cell.contentView并不是cell.view。
方法2:使用xib绘制Custom Cell View
这是自定义Cell最常见也是最省力的方法:1)
首先在xcode中创建custom xib,拖拽需要的控件到xib上,并做好布局和限制;2)新建自己的custom class,定义对应的outlet properties;3)将xib的class设置成对应的custom class,然后将outlet和控件连接起来;4)在适当的位置(一般为初始化的地方)调用registerNib:forCellReuseIdentifier:注册Cell;5)在tableView:cellForRowAtIndexPath:中调用dequeueReusableCellWithIdentifier:forIndexPath:复用cell
下面的这个示例演示了上述步骤。在这个示例中,首先创建Custom Cell和xib的界面,其中有一张大图,下面有两个独立的label,然后我使用了tableView:willDisplayCell:forRowAtIndexPath:对每一行Cell的背景颜色做出最终设置,而在tableView cellForRowAtIndexPath:中对Cell的内容进行填充:
Custom View:
@interface MyTableCellView : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *imageV
@property (weak, nonatomic) IBOutlet UILabel *
@property (weak, nonatomic) IBOutlet UILabel *
Custom Xib:
CustomXib.png
在table View Controller中:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup here ...
// register the cell to tell the system preparing to reuse it.
[self.tableView registerNib:[UINib nibWithNibName:@"TableCellView" bundle:nil] forCellReuseIdentifier:cellId];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// always reuse the cell
MyTableCellView *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
cell.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 250);
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"];
cell.imageView.image = [UIImage imageWithContentsOfFile:path];
NSDate *object = self.objects[indexPath.row];
cell.date.text = [object description];
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
NSLog(@"indexpath = %ld", indexPath.row);
if ( indexPath.row % 2 == 0) {
cell.backgroundColor = [UIColor redColor];
cell.backgroundColor = [UIColor greenColor];
CustomCell2.png
方法3:使用code定义一个Custom Cell Class
这个在本质上和上一种使用xib的方法是一样的,只不过一个是用代码完全定制,一个是借助xib操作。但是在Cell重用的方式上有一定区别。上一种方法中,需要调用registerNib:forCellReuseIdentifier:来注册重用的Cell,在这里就需要用registerClass:forCellReuseIdentifier:方法来注册。与之对应的,获取重用的Cell的时候,调用dequeueReusableCellWithIdentifier:forIndexPath:方法。
Class myClass = [MyTableCellView class];
[self.tableView registerClass: myClass forCellReuseIdentifier:@"CustomCell"];
MyTableCellView *cell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomCell" forIndexPath:path];
cell.label.text = @"text";
注意 dequeueReusableCellWithIdentifier:和dequeueReusableCellWithIdentifier:forIndexPath:的区别!!
如果你注册过Cell,在没有可用的cell时,前者会返回nil;而后者永远都会从注册的nib或者class中替你创建一个可用的Cell。也就是说,前者调用你需要手动检查nil,而后者不需要;
如果你从没有注册过cell,在没有可用的cell时,前者会返回nil,后者……直接崩溃!也就是说,调用后者你 必须确保注册过cell 。
2.2 访问Cell中的控件:
xib中使用outlet这个应该不用多说,在Cell的原型中(不管是Static cell还是Dynamic cell)定义outlet properties,然后在xib中拖拽连接对应的控件即可;Apple官方文档上的示意图:
connect_outlet.jpg
connect_static_objects.jpg
代码中使用viewWithTag:这个是获取parent view上某个特定view的快捷方法,首先需要设置一个sub view的tag,然后使用viewWithTag:来访问这个sub view。设置时可以通过xcode在xib中设置tag标签,也可以直接通过tag property手动设置:
mainLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 220.0, 15.0)];
mainLabel.tag = MAINLABEL_TAG;
// customize the label here...
[cell.contentView addSubview:mainLabel];
mainLabel = (UILabel *)[cell.contentView viewWithTag:MAINLABEL_TAG];
有关Table和Cell的性能需要注意的问题
关于这个话题,Apple并没有用过多的篇幅介绍,但是在官方开发文档中明确提出了3点意见:
注意重用(Reuse Cell)这点我们已经在上文中着重强调过了。
避免反复的调整Cell的布局(Avoid relayout of content)只在创建每一个Cell的时候布局一次,而不要每一次获取Cell的时候都去重新布局。
避免透明的subviews (Use opaque subviews)自定义cell的时候,尽可能避免使用透明的控件,因为透明控件在table滑动时将增大渲染开销。
本文主要从Static table和Dynamic table两方面总结了UITableView和UITableViewCell的核心使用方法和问题,并着重介绍了Custom Cell的几种方法和注意事项。
另外,有兴趣的话,UITableView还有另外几个比较关键的功能可以继续研究,一个是Editing mode,一个是Table Index,还有一个相对也很重要的功能自定义Header和Footer View。有空的话可以再总结一下。希望此篇能帮助到您。
日,完稿于南京。
一个不想做产品狗的程序猿不是一个好的架构狮13545人阅读
Ios tableview(38)
&原文链接 :/lbj96347/DynamicHeights&
TableViewCell Dynamic Heights
DynamicHeights是一个动态表格元素高度(动态TableViewCell)的例子。实际应用场景在iOS开发中会经常遇到不规律的TableViewCell,往往需要根据内容的多少而动态调整这些Cell的大小。在&中,有详细的解说开发的流程以及这么处理的原因。里面的大部分代码也来源于这位作者。
随着iOS 7的升级,这段09年编写的代码中已经有部分的代码被认为是不建议使用的,因此我对该项目部分代码进行了修改。便于日后方便使用或者学习参考之用。
博客翻译:iOS-动态调整UITableViewCell的高度
P.S : 以下内容代码部分,注释内容为我改进的代码段,减少issues警告。
大概你第一眼看来,动态调整高度是一件不容易的事情,而且打算解决它的第一个想法往往是不正确的。在这篇文章中我将展示如何使图表单元格的高度能根据里面文本内容来动态改变,同时又不必子类化UITableViewCell。你当然可以通过子类化它来实现,但是这样做会使得代码复杂因为设置高度是在图表本身的实例上而不是对单元格操作。下面你将会看到这其实是一件轻而易举的事情。对于图表来说能够动态调整高度是件很有意义的事情,我首先想到的需要这个功能的是当显示一列长度会变化的文本列表时,如果文本内容较少,它或许能够适合正常的单元格label,但是如果文本变长,就不得不重新设置单元格大小以便于显示全部的文本内容。我总结了重新设置单元格大小的主要步骤如下:
创建并添加一个UILabel作为单元格cell的子视图;在UITableView的委托方法: (CGFloat)tableView:(UITableView*)tableViewheightForRowAtIndexPath: (NSIndexPath *) indexPath中计算高度在UITableView的委托方法: (UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath: (NSIndexPath *) indexPath中计算UILabel的框大小。
下面我要详细介绍这些步骤,首先看一下程序输出截图:
在普通的图表中,你可以简单地用下面的方法设置单元格内label的文本内容:
[[cell textLabel] setText:@&Text for the current cell here.&];
也许你认为这样做就可以完全控制UILabel了,但是我发现我的任何要改变UILabel框大小的尝试都失败了,因此这并不是实现动态调整大小的一个好的候选方案。
我们需要设计一个UILabel然后把它添加到单元格的内容视图中。要实现它需要调用-cellForRowAtIndexPath,大致内容如下所示:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *
UILabel *label =
cell = [tv dequeueReusableCellWithIdentifier:@&Cell&];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@&Cell&] autorelease];
label = [[UILabel alloc] initWithFrame:CGRectZero];
//[label setLineBreakMode:UILineBreakModeWordWrap];
[label setLineBreakMode:NSLineBreakByWordWrapping];
//[label setMinimumFontSize:FONT_SIZE];
[label setMinimumScaleFactor:FONT_SIZE];
[label setNumberOfLines:0];
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
[[cell contentView] addSubview:label];
这并不是完整的代码因为我们仅仅在创建单元格的时候初始化它的label,这段代码对应调用-dequeueReusableCellWithIdentifier之后的判断模块if(cell == nil)。 在这里我想强调两点:第一个,我们可以注意到label有一个标签与其对应,因为调用了-setTag:1。当cell不等于nil时这个标签可以用到。第二点,我们通过调用[[cell contentView] addSubview:label]来将label添加到单元格的内容视图中,这个只是在label初始化的时候用到。每调用这个函数都会添加label到子视图序列中。下面我们会将这段代码补充完整,但之前先让我们看一下如何设置cell的高度。
计算cell的高度
在一个复杂的cell中,计算高度可能比较困难,但是你只需要关心那些高度会变化的部件就可以了。在我的例子中,唯一需要处理的就是添加到单元格中的label。我们根据文本的大小来计算cell 的高度,而文本的大小取决于文本的长度和文本字体。NSString类提供了函数-sizeWithFont来方便我们获取cell 的大小。下面的代码介绍了函数-heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexP
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
//CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
NSAttributedString *attributedText = [[NSAttributedString alloc]initWithString:text attributes:@{
NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE]
CGRect rect = [attributedText boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 2);
你会注意到我们用到了几个常量来计算cell 的大小,它们的定义如下所示:
#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 320.0f
#define CELL_CONTENT_MARGIN 10.0f
常量CELL_CONTENT_WIDTH是整个cell的宽度。CELL_CONTENT_MARGIN是我们定义的页边空白,FONT_SIZE是我们采用文本的字体大小。
首先我们要创建一个内容宽度的约束条件。CGSizeMake的第一个参量是总共的内容宽度减去两个页边空白。因为左边和右边各有一个页边空白。第二个参数是我们提供的最大数值。这个约束条件在后面的函数-sizeWithFont中将会用到。在-sizeWithFont中我们设置为UILineBreakModeWordWrap来获取在允许自动换行的情况和上面提到的约束条件下正确的大小。最后我们使用MAX宏设置cell的高度,并且保证cell 的高度不会小于44个像素,因为它返回size.height和44两个数中的最大值。最后,我们将上下的页边空白考虑进去得到最后的结果。
为了使得读者形象化的了解页边空白,下面一个截图可以看出有一个边界环绕着label。调用[[label layer] setBorderWidth:2.0f]可以显示该边界从而方便我们看到页边空白。
计算并设置UILabel框大小
在前面我们用来计算高度的方法也是我们用来设置UILabel框大小的方法。下面将-cellForRowAtIndexPath代码补充完整:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *
UILabel *label =
cell = [tv dequeueReusableCellWithIdentifier:@&Cell&];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@&Cell&] autorelease];
label = [[UILabel alloc] initWithFrame:CGRectZero];
//[label setLineBreakMode:UILineBreakModeWordWrap];
[label setLineBreakMode:NSLineBreakByWordWrapping];
//[label setMinimumFontSize:FONT_SIZE];
[label setMinimumScaleFactor:FONT_SIZE];
[label setNumberOfLines:0];
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
[[label layer] setBorderWidth:2.0f];
[[cell contentView] addSubview:label];
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
//CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
NSAttributedString *attributedText = [[NSAttributedString alloc]initWithString:text attributes:@{
NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE]
CGRect rect = [attributedText boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.
if (!label)
label = (UILabel*)[cell viewWithTag:1];
[label setText:text];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
要注意if(cell == nil)模块是初始化代码,只在cell创建的时候运行一次。该模块外部代码每次都会执行只要在每次数据更新或者窗口拖拽之后调用了-cellForRowAtIndexPath。
也就是说,每次都需要设置label中文本内容以及设置label外框大小。注意如果label处于未初始化状态,我们需要通过调用[cell viewWithTag:1]来获取UILabel的句柄。这段代码跟前面计算高度的代码基本相同。
动态计算单元格cell的高度真的并不困难。如果你有一个很复杂的cell,你只需要根据内容宽度和特定文本字体的大小来确定cell的高度。如果你不清楚你的外框显示在什么地方,只需要通过调用[[view layer] setBorderWidth:2.0f]来使外框显示即可。这会有助于你了解绘图过程以及更快地在更深的层次理解绘图显示的问题。
作者:Matt Long
翻译文章:友盟翻译组 stefaliu
原文链接:
翻译原文地址:(暂时未找到,抱歉了)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1468127次
积分:13011
积分:13011
排名:第825名
原创:148篇
转载:160篇
评论:113条
(5)(1)(6)(4)(1)(5)(7)(1)(1)(1)(3)(2)(2)(5)(11)(2)(1)(1)(1)(3)(6)(2)(3)(7)(4)(5)(4)(11)(2)(5)(6)(2)(23)(13)(21)(23)(60)(31)(9)(7)(3)

我要回帖

更多关于 ios删除tableviewcell 的文章

 

随机推荐