基于视图的NSTableView

时间:2012-11-07 01:35:48

标签: cocoa nstableview

我一直在靠墙试图想出tableView:heightOfRow:我想我需要帮助。我想为行内的textView做动态行高,似乎无法掌握该方法。我已经阅读了我能找到的所有内容,但实际上并不多。我可以使用此方法获取我想要的行大小,但只有在调整表的大小时。不可见的行在显示之前不会调整大小,并且会调整表的大小。

我添加了tableView:didAddRowView:forRow方法,并使用相同的基本思想,最终将行大小压缩到一行。与tableView:heightOfRow的工作方式不同:即使它是相同的代码。我猜测tableView:didAddRowView:forRow方法设置textView边界是以某种方式缩放。

这是我的(希望是相关的)代码:

- (CGFloat)tableView:(NSTableView *)tv heightOfRow:(NSInteger)row {
    if (tv == dataTableView) {
        NSInteger valueCol = [tv columnWithIdentifier:@"value"];
        NSTableCellView *valueView = [tv viewAtColumn:valueCol row:row makeIfNecessary:NO];

        if (valueView) {
            // Working on the interesting column and this row is visible
            NSRect bounds = [[valueView textField] bounds];
            id value = [[valueView textField] stringValue];

            NSFont *fieldFont = [[valueView textField] font];
            CGFloat adjustedHeight = [value heightForWidth:bounds.size.width font:fieldFont];
            CGFloat rowHeight = [tv rowHeight];
            if (adjustedHeight <= rowHeight) adjustedHeight = rowHeight;

            return adjustedHeight;
        }
    }
    return [tv rowHeight];
}


- (void)tableView:(NSTableView *)tv didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
    if (tv == dataTableView) {
        NSInteger valueCol = [tv columnWithIdentifier:@"value"];
        NSTableCellView *colView = [rowView viewAtColumn:valueCol];
        NSRect textFieldViewBounds = [[colView textField] bounds];
        NSTextField *colTextField = [colView textField];
        NSFont *colFont = [colTextField font];
        id value = [colTextField stringValue];
        CGFloat newHeight = [value heightForWidth:textFieldViewBounds.size.width font:colFont];
        NSSize colViewSize = colView.bounds.size;
        colViewSize.height = newHeight;
        textFieldViewBounds.size.height = newHeight;
        [colTextField setBounds:textFieldViewBounds];
    }
}

更新:新代码运行得更好,但在初始加载时仍有问题,有时还会滚动:

- (CGFloat)tableView:(NSTableView *)tv heightOfRow:(NSInteger)row {
    if (tv == dataTableView) {
        NSInteger valueCol = [tv columnWithIdentifier:@"value"];
        NSTableCellView *valueView = [tv viewAtColumn:valueCol row:row makeIfNecessary:NO];

        if (valueView) {
            // Working on the interesting column
            NSRect bounds = [[valueView textField] bounds];
            id value = [[valueView textField] stringValue];

            NSFont *fieldFont = [[valueView textField] font];
            CGFloat adjustedHeight = [value heightForWidth:bounds.size.width font:fieldFont];
            CGFloat rowHeight = [tv rowHeight];
            if (adjustedHeight <= rowHeight) adjustedHeight = rowHeight;

            return adjustedHeight;
        }
    }
    return [tv rowHeight];
}


- (void) tableView:(NSTableView *)tv didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
    if (tv == dataTableView) {
        [dataTableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row, 1)]];
    }
}

1 个答案:

答案 0 :(得分:0)

从你的代码中,我猜你想根据文本域单元格中的行数来改变行高,对吗?因此,如果您调整列或表的大小,或者输入新文本,则高度应该更改...?

IMO你不需要在-tableView中执行任何操作:didAddRowViewForRow:为时已晚,行视图应该已经有了它的最终高度。尝试修改视图框架可能会导致错误异常。由于您的文本字段位于NSTableCellView中(假设适当的布局约束,默认布局约束应该没问题),它应该在IB中根据您的设计显示,并且-tableView返回的行高:heigthOfRow:

-tableView:heigthOfRow:确实是你需要确定行高的方法。但是,您需要为调用方法的所有行返回适当的值,否则当滚动期间进入可见矩形时,行将不会显示在正确的高度。所以我会选择YES作为viewAfNecessary:viewAtColumn方法的参数。

然后,您需要让表在必要时更新行高(调整列,视图,可能输入新文本...)。例如,可以在-tableViewColumnDidResize(使用userinfo字典获取已调整大小的列)或编辑文本字段时执行此操作。 在那里,你需要在表视图上调用-noteHeightOfRowsWithIndexesChanged :.如果调整了列的大小,则为所有行调用它,并且-tableView:heigthOfRow:将返回所有高度。如果编辑了文本字段,您可能只想为其行调用它(但即使调用所有行的方法也应该这样做)。

我希望它有所帮助。