没有contentView框架计算UITableViewCell高度的最佳方法

Val*_*sov 9 iphone objective-c uitableview ios heightforrowatindexpath

摘要

鉴于我们并不总是知道单元格的框架或其内容视图将是什么(由于编辑,旋转,附件视图等),tableView:heightForRowAtIndexPath:当单元格包含一个单元格时,计算高度的最佳方法是什么?可变高度文本字段或标签?

我的一个UITableViewController's包含以下演示文稿:UITableViewCell与UITextView.

UITextView的宽度和高度应与UITableViewCell相同.

在此输入图像描述

我创建了UITableViewCell子类,然后使用UITextView初始化它(UITextView是我的UITableViewController的私有字段)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
     static NSString *CellIdentifier = @"TextViewCell";
     UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil) {
         cell = [[[BTExpandableTextViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier textView:_notesTextView] autorelease];
     }    
     return cell;
}
Run Code Online (Sandbox Code Playgroud)

我在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];
}
Run Code Online (Sandbox Code Playgroud)

当然我实现了以下UITableViewDataSource方法(看!我使用的是self.view.frame.size.width(但实际上我需要UITableViewCell contentView框架宽度):

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{

    CGFloat height  = [_notesTextView.text sizeWithFont:_notesTextView.font 
                                      constrainedToSize:CGSizeMake(self.view.frame.size.width, MAXFLOAT)].height;        
    CGFloat groupedCellCap = 20.0;     
    height          += groupedCellCap; 

    if(height < [BTExpandableTextViewCell minimumTextViewHeightWithFont:_notesTextView.font]){
        height = [BTExpandableTextViewCell minimumTextViewHeightWithFont:_notesTextView.font];
    }        
    return height;
}    
Run Code Online (Sandbox Code Playgroud)

我也实现了以下方法(这不是那么重要但不好发布它只是为了解释单元格的高度是动态的,它会在UITextView中更改文本后收缩或扩展)

 - (void)textViewDidChange:(UITextView *)textView{
    CGFloat height = [_notesTextView.text sizeWithFont:_notesTextView.font 
                                 constrainedToSize:CGSizeMake(_notesTextView.frame.size.width, MAXFLOAT)].height;
    if(height > _notesTextView.frame.size.height){
        [self.tableView beginUpdates];
        [self.tableView endUpdates];
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是: 加载视图后,UITableViewController按以下顺序调用方法:(删除一些,例如titleForHeaderInSection等,以简化)

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{ 
Run Code Online (Sandbox Code Playgroud)

然后才这样

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Run Code Online (Sandbox Code Playgroud)

看!我应该在cellForRowAtIndexPath之前返回正确的UITableViewCell高度!这意味着:我不知道UITableViewCell contentView框架.我无法以编程方式获得它.

宽度可以是以下之一:

  1. iPhone普通表,纵向方向
  2. iPhone普通表,横向定位
  3. iPhone分组表,纵向方向
  4. iPhone分组表,横向
  5. 和iPad一样(另外4个值)

并且不要忘记,由于UITableViewCell accessoryType,或者因为UITableView编辑状态,contentView框架可以更小.(例如,如果我们在任何编辑状态下使用任何高度的多线UILabel和任何accessoryView的UITableViewCell)

所以这个问题是根本的:我只是不能得到单元格contentView框架宽度用于约束,因为我应该在单元格布局contentView之前返回此高度.(顺便说一句,这是非常合乎逻辑的)但是这个contentView框架确实很重要.

当然有时我可以准确地知道这个宽度并"硬编码"它(例如:UITableViewCellAccessoryDisclosureIndicator有20 px宽度,而tableView不能处于编辑状态,那么我可以编写self.view.frame.size.width - 20和任务已经完成了)!或者有时contentView等于UITableViewController的视图框架!

有时我在-tableView:heightForRowAtIndexPath:方法中使用self.view.frame.width ...(就像现在一样,它工作得很好,但由于分组的UITableView不完美,应该减去一些常量值,它们是不同的2个设备*2个方向)

有时我在UITableViewCell中有一些#defined常量(如果我确切知道宽度)...

有时候我正在使用一些假的预先分配的UITableViewCell(什么只是愚蠢,但有时非常优雅,易于使用)...

但我不喜欢那样的东西.

什么是最好的决定? 也许我应该创建一个辅助类,它将使用以下参数进行初始化:附件视图,设备方向,设备类型,表视图编辑状态,表视图样式(普通,分组),控制器视图框架等等,将包括一些常量(如分组tableView偏移等)并使用它来查找预期的UITableViewCell contentView宽度?;)

谢谢

小智 1

表视图tableView:heightForRowAtIndexPath:在创建任何单元格之前使用该方法确定其 contentSize UITableViewCell。如果您停下来想一想,这是有道理的,因为您对 a 要做的第一件事UIScrollView就是设置它的 contentSize。我以前遇到过类似的问题,我发现最好有一个辅助函数,可以将内容放入 UITableViewCell 并预测该 的高度UITableViewCell。所以我认为你会想要创建某种数据结构来存储每个中的文本UITableViewCell,一个以 NSIndexPaths 作为键和文本作为值的 NSDictionary 会很好。这样,您就可以找到所需文本的高度,而无需引用UITableViewCell.