Высота строки NSTableView, основанная на NSStrings - PullRequest
5 голосов
/ 09 июля 2010

По сути, у меня есть NSTableView с 1 ​​столбцом, и я вставляю длинные строки в каждую строку. Однако не все строки длинные, поэтому я бы хотел, чтобы высота каждой строки была разной в зависимости от длины строки.

Я понял, что мне нужно спросить столбец, насколько он широк, а затем спросить строку, сколько строк она займет, если столбец такой широкий, а затем решить, насколько «высокой» будет NSCell. , Но как именно я это делаю? Я получил ширину столбца от:

[[[tableView tableColumns] objectAtIndex:0] width];

но я не могу понять, как спросить строку NSSt, сколько места она займет. Или, может быть, есть лучший способ сделать это?

Спасибо за любую помощь заранее.

Ответы [ 5 ]

10 голосов
/ 09 июля 2010

Создайте экземпляр NSTextFieldCell и сопоставьте его шрифт / размер / и т. Д.к ячейке данных вашего столбца.Запросите -cellSizeForBounds:, передавая прямоугольник желаемой ширины для столбца с большой высотой (FLT_MAX?).Результатом должен быть NSSize, высота которого вы можете использовать.

Будет сложнее, если у вас более одного многострочного текстового столбца, потому что вам нужно будет рассмотреть все ячейки в этой строке, принимая наибольшее значениеваша высота строки.Если вы ожидаете, что в среднем будет много строк, вы, вероятно, захотите кэшировать эту работу, обновляя ее по мере необходимости, а затем просто ссылаясь на нее при вызове метода делегата высоты строки.

8 голосов
/ 18 мая 2012

Код в соответствии с ответом выше ...

    NSString *string = [[_tableViewDataSourceArray objectAtIndex:rowIndex] 
                              valueForKey:@"StringToDisplay"];

    NSTableColumn *tableColoumn = [aTableView
                              tableColumnWithIdentifier:@"TableColumnIdentifier"];

    if (tableColoumn) 
    {
     NSCell *dataCell = [tableColoumn dataCell];
     [dataCell setWraps:YES];
     [dataCell setStringValue:string];
     NSRect myRect = NSMakeRect(0, 0, [tableColoumn width], CGFLOAT_MAX);
     heightOfRow =  [dataCell cellSizeForBounds:myRect].height;
    }
3 голосов
/ 17 июня 2014

Вот небольшое улучшение Ответ Роберта Альмейды (Первоначально я отправил это как правку, но он был отклонен, потому что "первоначальное значение или намерение поста будет потеряно").Я добавил сигнатуру метода и внес несколько других небольших изменений.

- (CGFloat)tableView:(NSTableView *)aTableView heightOfRow:(NSInteger)row {
    CGFloat heightOfRow = 100; // or some other default value

    // get the content for this table cell from the model
    NSString *string = [[_tableViewDataSourceArray objectAtIndex:rowIndex] 
                              valueForKey:@"StringToDisplay"];

    NSTableColumn *tableColumn = [aTableView
                              tableColumnWithIdentifier:@"TableColumnIdentifier"];

    if (tableColumn) {
        NSCell *dataCell = [tableColumn dataCell];
        [dataCell setWraps:YES];
        [dataCell setStringValue:string];

        // See how tall it naturally would want to be if given a restricted
        // width, but unbound height
        NSRect myRect = NSMakeRect(0, 0, [tableColumn width], CGFLOAT_MAX);
        heightOfRow = [dataCell cellSizeForBounds:myRect].height;
    }

    return heightOfRow;
}
2 голосов
/ 01 сентября 2015

Вот другое решение, которое хорошо работает в моем случае:

Objective-C:

- (double)tableView:(NSTableView *)tableView heightOfRow:(long)row
{
    if (tableView == self.tableViewTodo)
    {
        CKRecord *record = [self.arrayTodoItemsFiltered objectAtIndex:row];
        NSString *text = record[@"title"];

        double someWidth = self.tableViewTodo.frame.size.width;
        NSFont *font = [NSFont fontWithName:@"Palatino-Roman" size:13.0];
        NSDictionary *attrsDictionary =
        [NSDictionary dictionaryWithObject:font
                                    forKey:NSFontAttributeName];
        NSAttributedString *attrString =
        [[NSAttributedString alloc] initWithString:text
                                        attributes:attrsDictionary];

        NSRect frame = NSMakeRect(0, 0, someWidth, MAXFLOAT);
        NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
        [[tv textStorage] setAttributedString:attrString];
        [tv setHorizontallyResizable:NO];
        [tv sizeToFit];

        double height = tv.frame.size.height + 20;

        return height;
    }

    else
    {
        return 18;
    }
}

Swift:

func tableView(tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    if let log:Log = logsArrayController.arrangedObjects.objectAtIndex(row) as? Log {
        if let string: String = log.message! {

            let someWidth: CGFloat = tableView.frame.size.width
            let stringAttributes = [NSFontAttributeName: NSFont.systemFontOfSize(12)] //change to font/size u are using
            let attrString: NSAttributedString = NSAttributedString(string: string, attributes: stringAttributes)
            let frame: NSRect = NSMakeRect(0, 0, someWidth, CGFloat.max)
            let tv: NSTextView = NSTextView(frame: frame)
            tv.textStorage?.setAttributedString(attrString)
            tv.horizontallyResizable = false
            tv.sizeToFit()
            let height: CGFloat = tv.frame.size.height + 20 // + other objects...

            return height

        }

    }

    return 100 //Fail
}
2 голосов
/ 17 июня 2014

Мне нравится Ответ Роберта Альмейды , но он использует -[tableColumn dataCell], что, как утверждают в документации Apple, "действительно только для табличных представлений на основе ячеек".

Моя попытка приведена ниже.

В Интерфейсном Разработчике (в XCode: я использую 5.1.1 в настоящее время), установите NSTableView.

  • представление таблицы должно иметь Режим содержимого, установленный в На основе представления
  • один из столбцов должен иметь идентификатор WrapColumnIdentifier
  • , что столбец должен содержать NSTableCellView, который должен содержать NSTextField (и для понимания коданиже вы должны знать, что NSTextField содержит NSTextFieldCell, который является подклассом NSCell)
  • объект NSTextField должен иметь Layout, установленный в Wraps
  • объект NSTextFieldдолжна быть настроена маска автоматического изменения размера, в которой включены все шесть строк (сплошной красный), поэтому, когда таблица изменяет размеры ячейки таблицы, текстовое поле будет изменено и будет продолжать заполнять ячейку.

Здесьявляется методом NSTableViewDelegate для использования с этой настройкойЭто приводит к тому, что высота каждой строки таблицы устанавливается так, что «столбец переноса» (который содержит NSTextField) показывает свой текст без усечения.

- (CGFloat)tableView:(NSTableView *)aTableView heightOfRow:(NSInteger)aRow {
    NSTableColumn *tableColumn = [aTableView tableColumnWithIdentifier:@"WrapColumnIdentifier"];

    // obtain the view that would be used at this position in the table 
    // (ie at this column and row: I'm using this odd form of language so as 
    // to avoid the word "cell" and potential confusion with NSCell), 
    // populated with data from the model
    NSView* view = [self tableView:aTableView viewForTableColumn:tableColumn row:aRow];
    NSAssert([view isKindOfClass:[NSTableCellView class]], @"Expected view used in table to be NSTableCellView");
    NSTableCellView* tableCellView = (NSTableCellView*)view;

    // get the NSCell used by the NSTextField at this position in the table
    NSCell* cell = [[tableCellView textField] cell];

    // See how tall it naturally would want to be if given a restricted width,
    // but unbound height
    NSRect unboundHeightColumnRect = NSMakeRect(0, 0, [tableColumn width], CGFLOAT_MAX);
    CGFloat cellTextHeight = [cell cellSizeForBounds:unboundHeightColumnRect].height;

    // Apple's docs say this method must return a value greater than 0.
    // cellTextHeight might be 0 (eg if the model returns no data at this
    // position in the table).  Use the row height set for the table in IB 
    // as the minimum.
    return MAX(cellTextHeight, [tableView rowHeight]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...