UITableView cell.contentView.bounds.size.width меняется с повторным использованием ячеек - PullRequest
14 голосов
/ 08 июня 2011

Я использую cell.contentView.bounds.size.width для вычисления положения текстового поля в ячейке UITableView. Когда ячейка создана, код отладки сообщает о ширине как 302. Когда ячейка прокручивается за пределы экрана и затем снова включается, код отладки сообщает, что она составляет 280 - каждый раз. Похоже, он не хочет возвращаться к 302 и остается застрявшим на 280. Конечный результат заключается в том, что текстовое поле помещается в неправильное место во второй раз, когда поле помещается в contentView ячейки, хотя оно было помещено в правильное место в первый раз.

Я думаю, что цифра 22 важна, но я не знаю, что это такое. Предполагая, что это может быть стрелка раскрытия, я переместил код «Очистить ячейку» перед определением ширины, включая установку аксессуара на nada.

Кто-нибудь может сказать мне, что здесь происходит?

Код (с не относящимися к делу - что я знаю - вырванными вещами) выглядит так:

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }


    // Configure the cell.

    while( [cell.contentView.subviews count] ){
        id subview = [cell.contentView.subviews objectAtIndex:0];
        [subview removeFromSuperview];  
    }
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

8< snip!

    CGFloat theCellWidth = cell.contentView.bounds.size.width - 44.0;
    CGFloat theLineHeight = [[UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0] lineHeight]; 

    NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);

    if (0==section) {
        switch (row) {
            case 2:
                while( [cell.contentView.subviews count] ){
                    id subview = [cell.contentView.subviews objectAtIndex:0];
                    [subview removeFromSuperview];  
                }
                cell.selectionStyle = UITableViewCellSelectionStyleNone;
                cell.textLabel.text = @" ";
                cell.detailTextLabel.text = @"The Age";
                theAgeTextField.frame = CGRectMake(10.0, 2.0, theCellWidth, theLineHeight);
//                NSLog(@"cell.contentView %@",cell.contentView);
                theAgeTextField.text = theAge;
                theAgeTextField.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0];
                theAgeTextField.keyboardType = UIKeyboardTypeDecimalPad;
                theAgeTextField.borderStyle = UITextBorderStyleNone;
                theAgeTextField.userInteractionEnabled = NO;
                [cell.contentView addSubview:theAgeTextField];
                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                break;

8< snip! (lots of closing braces and other stuff omitted)

    return cell;
}

Хотите попробовать это дома, мальчики и девочки?

Начните с нового навигационного приложения. Поместите следующий код в RootViewController.m:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 5;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
    // Configure the cell.
    return cell;
}

В код по умолчанию необходимо внести только два изменения: изменение числа строк в разделе («return 5») и стиль ячейки должны быть UITableViewCellStyleSubtitle . Затем, когда вы запустите программу, вы увидите пять строк этого:

2011-06-18 11:10:19.976 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.978 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.979 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.980 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.982 TestTableCells[7569:207] cell.contentView.bounds.size.width 302

Перетащите несколько ячеек за пределы экрана (перетаскивание вверх - вниз ничего не делает), и когда они появятся снова, вы получите следующее:

2011-06-18 11:10:24.013 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.047 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.130 TestTableCells[7569:207] cell.contentView.bounds.size.width 320

Честно говоря, я чертовски разочарован этим, и мне очень хочется потратить 99 долларов (даже без работающего приложения), чтобы я мог пригласить кого-нибудь из Apple в этот раз.

У кого-нибудь есть идеи, что здесь происходит?

Спасибо!


Хотите увидеть что-нибудь более интересное? Попробуйте это вместо строки static NSString...:

    NSString *CellIdentifier = [NSString stringWithFormat: @"%d", arc4random() ];

    NSLog(@"%@",CellIdentifier);

Теперь, каждый раз, ширина в журнале равна всегда 302. Тогда может показаться, что повторно используемая ячейка имеет ширину содержимого, отличную от исходной ячейки.

Опять ... интересно ... кто-нибудь понял?

Ответы [ 3 ]

10 голосов
/ 18 июня 2011

Я подозреваю, что то, что вы видите, связано с изменением вспомогательного представления ячейки, которое в конечном итоге изменит представление содержимого в следующий раз, когда ячейка выполнит -layoutSubviews. Это должно происходить, когда ячейка добавляется в таблицу, но до этого границы представления содержимого не будут обновляться.

Несмотря на это, я не понимаю, почему это будет проблемой. Похоже, вас интересует только установка ширины theAgeTextField, поэтому, если вы измените ее размер относительно текущей ширины представления содержимого и установите его флажки autoresizingMask, чтобы придать ему гибкую ширину, тогда он должен увеличиваться или уменьшаться по мере необходимости, когда изменяются границы представления содержимого.

Если вам нужно более детальное поведение макета, вероятно, все это должно происходить в подклассе UITableViewCell. См. -prepareForReuse и -layoutSubviews о возможностях настройки ячейки и ее подпредставлений. Ваш источник данных должен иметь возможность просто передать theAge экземпляру подкласса вашей ячейки и не заботиться о деталях того, как это будет отображаться.

1 голос
/ 11 октября 2012

Я столкнулся с тем же, за исключением того, что смещение было 20 вместо 22. Я думаю, что ответ Ионы на правильном пути, но для быстрого обходного пути, позволяющего избежать изменения размеров ячеек cell.contentView.frame / bounds, которые я просто использовал cell.frame / bounds в качестве справочного материала для размещения представлений в содержимом ячейки contentView.

0 голосов
/ 07 мая 2012

Вы должны реализовать высоту для метода делегата строки и выполнить все свои вычисления там

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

// do math

return newheight;
}

Это даст вам то, что вы ищете, у вас также есть доступ к пути индекса, чтобы вы могли легко найтистроки в вашем массиве и делайте все, что вам нужно, в противном случае вы получите размер повторно используемой строки из очереди, который всегда равен размеру строки по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...