Ios 不使用contentView框架计算UITableViewCell高度的最佳方法
摘要 考虑到我们并不总是知道单元格或其内容视图的框架是什么(由于编辑、旋转、附件视图等),当单元格包含可变高度文本字段或标签时,在Ios 不使用contentView框架计算UITableViewCell高度的最佳方法,ios,objective-c,iphone,uitableview,heightforrowatindexpath,Ios,Objective C,Iphone,Uitableview,Heightforrowatindexpath,摘要 考虑到我们并不总是知道单元格或其内容视图的框架是什么(由于编辑、旋转、附件视图等),当单元格包含可变高度文本字段或标签时,在表格视图:heightForRowAtIndexPath:中计算高度的最佳方法是什么 我的UITableViewController的一个包含以下演示文稿: UITableViewCell和UITextView UITextView的宽度和高度应与UITableViewCell相同 我创建了UITableViewCell子类,然后用UITextView初始化它(UI
表格视图:heightForRowAtIndexPath:
中计算高度的最佳方法是什么
我的UITableViewController的一个包含以下演示文稿:
UITableViewCell和UITextView
UITextView的宽度和高度应与UITableViewCell相同
我创建了UITableViewCell子类,然后用UITextView初始化它(UITextView是我的UITableViewController的一个私有字段)
我在UITableViewCell子类中实现了以下方法:
- (void)layoutSubviews{
[super layoutSubviews];
CGFloat height = [textView.text sizeWithFont:textView.font constrainedToSize:CGSizeMake(textView.frame.size.width, MAXFLOAT)].height + textView.font.lineHeight;
textView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, (height < textView.font.lineHeight * 4) ? textView.font.lineHeight * 4 : height);
[self.contentView addSubview:textView];
}
现在,我的问题是:
加载视图后,UITableViewController将按以下顺序调用方法:(为了简化,我将删除一些方法,如titleForHeaderInSection等)
只有那时
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
看!我应该在cellForRowAtIndexPath之前返回正确的UITableViewCell高度!
这意味着:我不知道UITableViewCell内容视图框架。我无法通过编程来获取它
此宽度可以是以下宽度之一:
iPhone普通桌,纵向
iPhone普通桌,横向
iPhone分组表,纵向
iPhone分组表,横向
iPad也是如此(另外4个值)
不要忘记,由于UITableViewCell accessoryType或UITableView编辑状态,contentView框架可以更小。(例如,如果我们的UITableViewCell在任何编辑状态下具有任意高度的多行UILabel,并且具有任何accessoryView)
所以这个问题很基本:我无法获取单元格contentView帧宽度进行约束,因为我应该在单元格布局contentView之前返回这个高度。(顺便说一句,这是非常合乎逻辑的)但是这个contentView框架真的很重要
当然,有时我可以准确地知道这个宽度,并“硬编码”它
(例如:UITableViewCellAccessoryDisclosureIndicator的宽度为20 px,tableView不能处于编辑状态,那么我可以写入self.view.frame.size.width-20,任务就完成了)!
或者有时contentView等同于UITableViewController的图幅
有时我在-tableView:heightforrowatinexpath:method.中使用self.view.frame.width。。(就像现在一样,它工作得很好,但不是很完美,因为分组的UITableView应该减去一些常量值,对于2个设备*2个方向,它们是不同的)
有时我在UITableViewCell中定义了一些常量(如果我确切知道宽度的话)
有时我使用一些虚拟的预分配UITableViewCell(这很愚蠢,但有时非常优雅且易于使用)
但我不喜欢这些
最好的决定是什么?
也许我应该创建一些助手类,该类将使用以下参数进行初始化:
附件视图、设备方向、设备类型、表视图编辑状态、表视图样式(普通、分组)、控制器图幅,以及其他一些,其中包括一些常量(如分组表视图偏移量等),并使用它来查找预期的UITableViewCell内容视图宽度?;)
谢谢在创建任何UITableViewCell
单元格之前,表视图使用tableView:heightforrowatinexpath:
方法确定其内容大小。如果您停下来想一想,这是有意义的,因为您使用UIScrollView
要做的第一件事就是设置其contentSize。我以前也遇到过类似的问题,我发现最好有一个helper函数,它可以将内容放入UITableViewCell并预测该UITableViewCell
的高度。因此,我认为您需要创建某种数据结构,将文本存储在每个UITableViewCell
中,这是一个NSDictionary,NSINDExpath作为键,文本作为值,这样做很好。这样,您就可以在不引用UITableViewCell
的情况下找到所需文本的高度。尽管您可以在UITableViewCell子类的'-layoutSubviews'中真正动态地计算表视图单元格中包含的标签的高度,但没有类似的方法(据我所知)对于表格视图委托的'-tableView:heightForRowAtIndexPath:'中的单元格高度
考虑这一点:
- (void)layoutSubviews
{
[super layoutSubviews];
CGSize size = [self.textLabel.text sizeWithFont:self.textLabel.font
constrainedToSize:CGSizeMake(self.textLabel.$width, CGFLOAT_MAX)
lineBreakMode:self.textLabel.lineBreakMode];
self.textLabel.$height = size.height;
}
不幸的是,到调用“-tableView:heightforrowatinexpath:”时,这还为时过早,因为cell.textlab.frame
尚未设置为CGRectZero={{0,0},{0,0}
好吧,无论是内容视图的框架,还是对单个标签的框架进行汇总,您都无法做到这一点
我能想到的唯一方法是想出一个方便的类、方法、常量或诸如此类的东西,试图在任何设备上覆盖任何设备方向上的所有可能宽度:
@interface UITableView (Additions)
@property (nonatomic, readonly) CGFloat padding;
@end
@implementation UITableView (Additions)
- (CGFloat)padding
{
if (self.formStyle == PTFormViewStylePlain) {
return 0;
}
if (self.$width < 20.0) {
return self.$width - 10.0;
}
if (self.$width < 400.0 || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return 10.0;
}
return MAX(31.0, MIN(45.0, self.$width * 0.06));
}
@end
@接口UITableView(添加)
@属性(非原子,只读)CGFloat填充;
@结束
@实现UITableView(添加)
-(CGFloat)填充
{
if(self.formStyle==PTFormViewStylePlain){
返回0;
}
if(自宽<20.0){
返回自。$width-10.0;
}
if(self.$width<400.0 | |[[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone){
返回10.0;
}
返回最大值(31.0,最小值(45.0,自身$width*0.06));
}
@结束
还要注意的是,最近我们还推出了新的iPhone5横向4英寸宽(568而不是480)
这整件事很令人不安,我知道。。。干杯。您不是决定表视图数据源和委托方法调用顺序的人。这是由数据源和委托UITableView类完成的,因此
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)layoutSubviews
{
[super layoutSubviews];
CGSize size = [self.textLabel.text sizeWithFont:self.textLabel.font
constrainedToSize:CGSizeMake(self.textLabel.$width, CGFLOAT_MAX)
lineBreakMode:self.textLabel.lineBreakMode];
self.textLabel.$height = size.height;
}
@interface UITableView (Additions)
@property (nonatomic, readonly) CGFloat padding;
@end
@implementation UITableView (Additions)
- (CGFloat)padding
{
if (self.formStyle == PTFormViewStylePlain) {
return 0;
}
if (self.$width < 20.0) {
return self.$width - 10.0;
}
if (self.$width < 400.0 || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return 10.0;
}
return MAX(31.0, MIN(45.0, self.$width * 0.06));
}
@end