故事板中的自定义单元格行高度设置没有响应

问题描述 投票:210回答:18

我正在尝试调整表格视图中其中一个单元格的单元格高度。我正在从相关单元格的“尺寸检查器”中的“行高”设置中调整大小。当我在iPhone上运行应用程序时,单元格的默认大小设置为表格视图中的“行大小”。

如果我更改表视图的“行大小”,则所有单元格的大小都会更改。我不想这样做,因为我只想要一个单元格的自定义大小。我已经看到很多帖子都有针对该问题的程序化解决方案,但我更愿意通过故事板来实现,如果可能的话。

ios uitableview ios5 storyboard xcode4.2
18个回答
291
投票

在动态单元格上,在UITableView上设置的rowHeight总是覆盖单个单元格的rowHeight。

但是在静态单元格上,在单个单元格上设置的rowHeight可以覆盖UITableView。

不确定这是不是一个bug,Apple可能是故意这样做的?


5
投票

您可以使用原型cells与自定义height,然后调用cellForRowAtIndexPath:并返回其frame.height。:。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self tableView:tableView
                    cellForRowAtIndexPath:indexPath];
    return cell.frame.size.height;
}

4
投票

如果要设置静态行高,可以执行以下操作:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 120;
}

4
投票

我最近一直在努力解决这个问题。我的问题是上面使用heightForRowAtIndexPath:方法发布的解决方案适用于模拟器中的iOS 7.1,但是通过简单地切换到iOS 8.1完全搞砸了结果。

我开始阅读更多关于自我调整细胞的信息(在iOS 8中引入,read here)。很明显,在iOS 8中使用UITableViewAutomaticDimension会有所帮助。我尝试使用该技术并删除了heightForRowAtIndexPath:和voila的使用,它现在在iOS 8中运行完美。但后来iOS 7却没有。我该怎么办?我需要适用于iOS 7的heightForRowAtIndexPath:而不适用于iOS 8。

这是我的解决方案(为了简洁起见而修剪)借用@JosephH上面发布的答案:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.estimatedRowHeight = 50.;
    self.tableView.rowHeight = UITableViewAutomaticDimension;

    // ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        return UITableViewAutomaticDimension;

    } else {
        NSString *cellIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
        static NSMutableDictionary *heightCache;
        if (!heightCache)
            heightCache = [[NSMutableDictionary alloc] init];
        NSNumber *cachedHeight = heightCache[cellIdentifier];
        if (cachedHeight)
            return cachedHeight.floatValue;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    CGFloat height = cell.bounds.size.height;
    heightCache[cellIdentifier] = @(height);
    return height;
    }
}

- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath {
    NSString * reuseIdentifier;
    switch (indexPath.row) {
        case 0:
            reuseIdentifier = EventTitleCellIdentifier;
            break;
        case 2:
            reuseIdentifier = EventDateTimeCellIdentifier;
            break;
        case 4:
            reuseIdentifier = EventContactsCellIdentifier;
            break;
        case 6:
            reuseIdentifier = EventLocationCellIdentifier;
            break;
        case 8:
            reuseIdentifier = NotesCellIdentifier;
            break;
        default:
            reuseIdentifier = SeparatorCellIdentifier;
            break;
    }

    return reuseIdentifier;
}

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@“8.0”)实际上来自我正在使用的一组宏定义,我在某处找到了(非常有用)。它们被定义为:

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

1
投票

对于动态单元格,UITableView上设置的rowHeight始终会覆盖单个单元格的rowHeight。如果行内的内容,只需计算动态高度。


1
投票

使用Swift 4在XCode 9上工作时出现同样的问题。

为单元格内的UI元素添加AutoLayout,自定义单元格行高度将按指定的方式相应地工作。


0
投票

我能找到的唯一真正的解决方案就是这个

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = ...; // Instantiate with a "common" method you'll use again in cellForRowAtIndexPath:
    return cell.frame.size.height;
}

这有效,并且如果重复StoryBoard中已经存在的逻辑,则不允许有可怕的开关。不确定性能,但我想当到达cellForRow:时,细胞已被初始化,它的速度一样快。当然这里可能存在附带损害赔偿,但看起来它在我这里工作正常。

我也在这里发布:https://devforums.apple.com/message/772464

编辑:Ortwin Gentz提醒我,将为TableView的所有单元格调用heightForRowAtIndexPath:,而不仅仅是可见的单元格。听起来合乎逻辑,因为iOS需要知道能够显示正确滚动条的总高度。这意味着它可能适用于小型TableView(如20个单元格)但在1000 Cell TableView上忘记了它。

此外,XML的前一个技巧:与我的第一个评论相同。正确的价值已经存在。


0
投票

添加为评论,但发布为可见性的答案:

如果您最初将表视图设置为“静态单元”,然后将其更改为“动态原型”,则似乎也存在问题。我有一个问题,甚至heightForRowAtIndexPath的委托方法被忽略了。我首先通过直接编辑故事板XML来解决它,然后最终从头开始重建故事板场景,从一开始就使用动态原型。


0
投票

鉴于我没有通过Interface Builder找到任何解决这个问题的方法,我决定使用两个动态单元在Swift中发布一个程序化解决方案,即使最初的问题是通过Interface Builder要求解决方案。无论我认为它对Stack Overflow社区有用:

    import UIKit

    enum SignInUpMenuTableViewControllerCellIdentifier: String {
       case BigButtonCell = "BigButtonCell"
       case LabelCell = "LabelCell"
    }

    class SignInUpMenuTableViewController: UITableViewController {
            let heightCache = [SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell : CGFloat(50),
                              SignInUpMenuTableViewControllerCellIdentifier.LabelCell : CGFloat(115)]

    private func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> SignInUpMenuTableViewControllerCellIdentifier {
        if indexPath.row == 2 {
            return SignInUpMenuTableViewControllerCellIdentifier.LabelCell
        } else {
            return SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell
        }
    }

   override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
       return self.heightCache[self.cellIdentifierForIndexPath(indexPath)]!
   }

   ...

  }

0
投票

您可以做的另一件事是转到文档大纲,选择嵌套原型单元格的表格视图。然后在“大小”检查器上,将表格视图“行高”更改为所需的值,并取消选中“自动”框。


84
投票

如果您使用UITableViewController,请实现此方法:

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

在行的功能中,您可以选择高度。例如,

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
       return 100;
    } 
    else {
       return 60;
    }
}

在此示例中,第一行高度为100像素,其他行高度为60像素。

我希望这个可以帮助你。


34
投票

对于动态细胞,在rowHeight上设置的UITableView总是覆盖单个细胞的rowHeight

这个行为是,IMO,一个bug。任何时候你必须在两个地方管理你的UI很容易出错。例如,如果您在故事板中更改单元格大小,则必须记住在heightForRowAtIndexPath:中更改它们。在Apple修复bug之前,目前最好的解决方法是覆盖heightForRowAtIndexPath:,但是使用故事板中的实际原型单元来确定高度而不是使用magic numbers。这是一个例子:

- (CGFloat)tableView:(UITableView *)tableView 
           heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    /* In this example, there is a different cell for
       the top, middle and bottom rows of the tableView.
       Each type of cell has a different height.
       self.model contains the data for the tableview 
    */
    static NSString *CellIdentifier;
    if (indexPath.row == 0) 
        CellIdentifier = @"CellTop";
    else if (indexPath.row + 1 == [self.model count] )
        CellIdentifier = @"CellBottom";
    else
        CellIdentifier = @"CellMiddle";

    UITableViewCell *cell = 
              [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    return cell.bounds.size.height;
}

这将确保在运行时自动获取原型单元格高度的任何更改,您只需在一个位置管理UI:故事板。


22
投票

我已经构建了各种答案/注释提示的代码,以便这适用于使用原型单元的故事板。

这段代码:

  • 不需要将单元格高度设置在故事板中明显位置以外的任何位置
  • 出于性能原因缓存高度
  • 使用公共函数获取索引路径的单元标识符,以避免重复逻辑

感谢Answerbot,Brennan和lensovet。

- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = nil;

    switch (indexPath.section)
    {
        case 0:
            cellIdentifier = @"ArtworkCell";
            break;
         <... and so on ...>
    }

    return cellIdentifier;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
    static NSMutableDictionary *heightCache;
    if (!heightCache)
        heightCache = [[NSMutableDictionary alloc] init];
    NSNumber *cachedHeight = heightCache[cellIdentifier];
    if (cachedHeight)
        return cachedHeight.floatValue;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    CGFloat height = cell.bounds.size.height;
    heightCache[cellIdentifier] = @(height);
    return height;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    <... configure cell as usual...>

20
投票

实际上有两个地方你需要改变行高,首先是单元格(你已经改变了),现在选择表格视图并检查尺寸检查器


11
投票

我认为这是一个错误。

尝试不是通过实用程序检查器调整高度,而是直接在故事板上拖动鼠标。

我用这种方法解决了这个问题。


9
投票

如果您使用的是swift,请使用这样的方法。不要使用故事板来选择行高。以编程方式设置表行高度,如下所示,

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if indexPath.row == 0 || indexPath.row == 1{
        let cell = self.tableView.dequeueReusableCellWithIdentifier("section1", forIndexPath: indexPath) as! Section1TableViewCell
        self.tableView.rowHeight = 150
        cell.label1.text = "hiiiiii"
        cell.label2.text = "Huiiilllllll"
        return cell

    } else {

        let cell = self.tableView.dequeueReusableCellWithIdentifier("section2", forIndexPath: indexPath) as! Section2TableViewCell
        self.tableView.rowHeight = 60
        cell.label3.text = "llll"
        return cell
    }

}

6
投票

在XML视图中打开故事板并尝试编辑所需元素的rowHeight属性。

当我尝试为我的原型行设置自定义rowHeight时,它对我有用。它不是通过检查员工作,但通过XML工作。


6
投票

您可以通过以下行从故事板获取UITableviewCell(在UITableviewController - 静态单元格中)的高度。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
   CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];

    return height;
}
© www.soinside.com 2019 - 2024. All rights reserved.