Подтвердить что ты не робот

UILabel иногда не правильно обматывает текст (автомат)

У меня есть установка uilabel в представлении. Он не имеет ограничения ширины, но вместо этого его ширина определяется ведущим ограничением на уменьшенное изображение и конечным ограничением к краю представления.

enter image description here

На этикетке установлено 0 строк и на перенос слов. Я понимаю, что это должно привести к тому, что рама uilabel будет расти, и действительно это происходит иногда. (Предыдущий в макет авто, я бы вычислил и обновил фрейм метки в коде).

Таким образом, в результате, он работает правильно, а не в других. См. Большинство ячеек, работающих там правильно, но последняя ячейка кажется слишком большой. На самом деле это правильный размер. Название "Fair Oaks Smog Check Test" фактически заканчивается "Only". Таким образом, моя оценка размера ячейки правильная, она должна быть такого размера. Однако ярлык не обертывает текст по любой причине. Его ширина рамки не распространяется вправо, поэтому проблема не возникает.

enter image description here

Итак, что здесь происходит? Он на 100% совместим, всегда на этой ячейке, а не над ней, что заставляет меня думать, что это связано с размером текста, и UILabel не перекладывает текст после того, как это представление добавлено в ячейку (что делает ее фактически меньшей шириной).

Любые мысли?

Дополнительная информация

Высота ячеек вычисляется из одной ячейки ячейки, которую я создаю и сохраняю в статической переменной:

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.items.count == 0) {
        return 60;
    }
    static TCAnswerBuilderCell *cell = nil;
    static dispatch_once_t pred;

    dispatch_once(&pred,
                  ^{
                      // get a sample cellonce
                      cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL];
                  });
    [cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
    return [cell heightForCellWithTableWidth:self.tableView.frame.size.width];
}

Я настраиваю ячейку с моим объектом данных "на лету", а затем вызываю метод, который у меня есть, который вычисляет высоту ячейки с заданной шириной таблицы (не всегда может полагаться на исходный кадр ячейки).

Это, в свою очередь, вызывает метод высоты на моем представлении, так как на самом деле ярлык живет:

- (CGFloat)heightForCellWithTableWidth:(CGFloat)tableWidth {
    // subtract 38 from the constraint above
    return [self.thirdPartyAnswerView heightForViewWithViewWidth:tableWidth - 38];
}

Этот метод определяет высоту, вычисляя правильную ширину метки и затем вычисляя:

- (CGFloat)heightForViewWithViewWidth:(CGFloat)viewWidth {
    CGFloat widthForCalc = viewWidth - self.imageFrameLeadingSpaceConstraint.constant - self.thumbnailFrameWidthConstraint.constant - self.titleLabelLeadingSpaceConstraint.constant;
    CGSize size = [self.titleLabel.text sizeWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(widthForCalc, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
    CGFloat returnHeight = self.frame.size.height - self.titleLabel.frame.size.height + size.height;
    CGFloat height = returnHeight < self.frame.size.height ? self.frame.size.height : returnHeight;
    return height;
}

Это работает на 100% правильно.

Ячейки создаются, очевидно, в cellForRowAtIndexPath и сразу настраиваются:

if (self.items.count > 0) {
    TCAnswerBuilderCell *cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL forIndexPath:indexPath];
    [cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
    return cell;
}

В конфигурации ячейки мое представление загружается из ниба (он повторно используется в другом месте, поэтому он не находится непосредственно в ячейке). Ячейка добавляет его следующим образом:

- (void) configureCellWithThirdPartyObject:(TCThirdPartyObject *)object {
    self.detailDisclosureImageView.hidden = NO;
    if (!self.thirdPartyAnswerView) {
        self.thirdPartyAnswerView = [TCThirdPartyAPIHelper thirdPartyAnswerViewForThirdPartyAPIServiceType:object.thirdPartyAPIType];
        self.thirdPartyAnswerView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.contentView addSubview:self.thirdPartyAnswerView];
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_thirdPartyAnswerView]-38-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];
    }
    [self.thirdPartyAnswerView configureViewForThirdPartyObject:object forViewStyle:TCThirdPartyAnswerViewStyleSearchCell];
}

Наконец, моя конфигурация вида выглядит следующим образом:

- (void) configureViewForThirdPartyObject:(TCTPOPlace *)object forViewStyle:(TCThirdPartyAnswerViewStyle) style {
    self.titleLabel.text = object.name;
    self.addressLabel.text = [NSString stringWithFormat:@"%@, %@, %@", object.address, object.city, object.state];
    self.ratingsLabel.text = [NSString stringWithFormat:@"%d Ratings", object.reviewCount];
    NSString *ratingImageName = [NSString stringWithFormat:@"yelp_star_rating_%.1f.png", object.rating];
    UIImage *ratingsImage = [UIImage imageNamed:ratingImageName];
    if (ratingsImage) {
        self.ratingImageView.image = ratingsImage;
    }
    if (object.imageUrl) {
        [self.thumbnailImageView setImageWithURL:[NSURL URLWithString:object.imageUrl] completed:nil];
    }
}

Это своего рода решение, но я не понимаю, почему

  • My subview был разработан с шириной 320, но не имеет ограничений для ширины
  • Подкатегория была добавлена ​​в ячейку, но с горизонтальными ограничениями, которые выглядят следующим образом:
    • @"|[_thirdPartyAnswerView]-38-|"
  • Представление было настроено сразу после добавления в ячейку, то есть текст для titleLabel был установлен сразу.
  • По какой-то причине текст был выложен так, как если бы представление имело полные 320 вместо 282.
  • Ярлык никогда не обновлялся, несмотря на то, что кадр подвью был обновлен до 282, и на этикетке были ограничены ограничения, которые позволяли бы правильно определять размер.
  • Изменение размера представления в xib для 282 устраняет проблему, потому что метка имеет нужный размер для начала.

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

решаемые

См. ответ Мэтта ниже: qaru.site/info/133324/...

Если вы не прочитали комментарий, основная проблема заключалась в том, что я неосознанно устанавливал preferredMaxLayoutWidth через IB при проектировании представления с большей шириной, чем это было бы показано (в некоторых случаях). preferredMaxLayoutWidth - это то, что используется для определения того, где текст обертывается. Поэтому, даже если мой взгляд и titleLabel правильно изменяются, preferredMaxLayoutWidth все еще находится в старом значении и вызывает обертывание в неожиданных точках. Вместо этого вместо параметра titleLabel следует установить автоматический размер (⌘ = в IB) и динамически обновить preferredMaxLayoutWidth в layoutSubviews до вызова супер. Спасибо Мэтту!

4b9b3361

Ответ 1

Я - тот, кто написал приложение, которое использует автозапуск пяти ярлыков в ячейке в таблице, чьи ячейки имеют разную высоту, где метки изменяются в соответствии с тем, что в них, и это действительно работает. Поэтому я собираюсь предложить, что причина, по которой у вас возникли проблемы, может заключаться в том, что ваши ограничения недоопределяют макет, то есть у вас есть неоднозначный макет для элементов ячейки. Я не могу проверить эту гипотезу, потому что я не вижу ваших ограничений. Но вы можете легко проверить (я думаю), используя po [[UIWindow keyWindow] _autolayoutTrace] при паузе в отладчике.

Также у меня есть еще одно предложение (извините, просто набросите на вас): убедитесь, что вы устанавливаете метку preferredMaxLayoutWidth. Это важно, потому что это ширина, на которой этикетка перестанет расти горизонтально и начнет расти вертикально.

Ответ 2

У меня была такая же проблема и она была решена с помощью предложения этого ответа. В подклассе UILabel я разместил этот код:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = self.bounds.size.width;
}

Я не понимаю, почему это не поведение по умолчанию UILabel, или, по крайней мере, почему вы не можете просто включить это поведение с помощью флага.

Я немного обеспокоен тем, что preferredMaxLayoutWidth устанавливается в середине процесса компоновки, но я не вижу легкого пути.

Ответ 3

Кроме того, убедитесь, что вы передаете целочисленные числа вашим ограничениям макета в коде.

Для меня случилось, что после некоторых вычислений (например, convertPoint: toView:), я проходил что-то вроде 23.99999997, и в конечном итоге это привело к отображению двухстрочной метки в виде однострочного (хотя его рамка, казалось, была правильно рассчитан). В моем случае CGRectIntegral сделал трюк!

Ошибки округления могут убить ya:)