的UILabel不能正确文本换行有时(自动布局) [英] UILabel not wrapping text correctly sometimes (auto layout)

查看:2248
本文介绍了的UILabel不能正确文本换行有时(自动布局)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个观点一个UILabel设置。它不具有一个宽度约束,但它的宽度,而不是由一个主导约束于缩略图图像,并且一个尾部约束到该视图的边缘确定。

标签设置有0线,并自动换行。我的理解是,这应该引起的UILabel增长的​​框架,而事实上它有时做。 (previous自动布局,我会计算并更新code标签的帧)。

所以结果是,它正常工作在某些情况下,而不是其他。见工作正常那里大多数细胞,但最后一个单元格显得太大。事实上,它是正确的大小。标题中的Fair Oaks的烟雾检查测试实际上只有结尾。所以,我对细胞的大小测算是正确的,它应该是大小。然而,标签不换行无论出于何种原因的文本。它的边框宽度不扩展关闭的权利,所以这不是问题。

那么,什么是怎么回事?它是100%一致,总是在该小区和不它上面的那些,这使我认为它有关的文本的大小,和的UILabel不重新铺设的文本,一旦这一观点被加入到细胞(其使得它实际上更小的宽度明智的)。

有什么想法?

一些额外的信息

细胞的高度从一个样品池计算创建并存储在一个静态变量:

   - (CGFloat的)的tableView:(UITableView的*)的tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    如果(self.items.count == 0){
        返回60;
    }
    静态TCAnswerBuilderCell *电池=零;
    静态dispatch_once_t preD;    dispatch_once(安培; preD,
                  ^ {
                      //获取样本cellonce
                      电池= [的tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL];
                  });
    [细胞configureCellWithThirdPartyObject:self.items [indexPath.row]];
    返回[单元heightForCellWithTableWidth:self.tableView.frame.size.width];
}

我配置具有在飞行我的数据对象中的细胞,然后调用一个方法我有在其上,其计算与给定表宽度的小区的​​高度(不能总是依赖细胞框架上是正确最初)

这反过来要求对我的看法高度的方法,因为它确实是它的标签是住:

   - (CGFloat的)heightForCellWithTableWidth:(CGFloat的)tableWidth {
    //从上面的限制减去38
    返回[self.thirdPartyAnswerView heightForViewWithViewWidth:tableWidth - 38]。
}

此方法通过计算出标签的正确宽度,然后做一个计算确定的高度:

   - (CGFloat的)heightForViewWithViewWidth:(CGFloat的)viewWidth {
    CGFloat的widthForCalc = viewWidth - self.imageFrameLeadingSpaceConstraint.constant - self.thumbnailFrameWidthConstraint.constant - self.titleLabelLeadingSpaceConstraint.constant;
    CGSize大小= [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的高度= returnHeight< self.frame.size.height? self.frame.size.height:returnHeight;
    返回高度;
}

这正常工作100%。

的细胞在明显的cellForRowAtIndexPath创建并立即进行配置:

 如果(self.items.count大于0){
    TCAnswerBuilderCell *电池= [的tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL forIndexPath:indexPath];
    [细胞configureCellWithThirdPartyObject:self.items [indexPath.row]];
    返回细胞;
}

在电池的结构中,我认为是从笔尖加载(它在别处再次使用,这就是为什么它不是直接在细胞)。细胞将其添加如下:

   - (无效)configureCellWithThirdPartyObject:(TCThirdPartyObject *){对象
    self.detailDisclosureImageView.hidden = NO;
    如果(!self.thirdPartyAnswerView){
        self.thirdPartyAnswerView = [TCThirdPartyAPIHelper thirdPartyAnswerViewForThirdPartyAPIServiceType:object.thirdPartyAPIType];
        self.thirdPartyAnswerView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.contentView addSubview:self.thirdPartyAnswerView];
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@| [_thirdPartyAnswerView] -33- |选项​​:NSLayoutFormatAlignAllCenterY指标:无意见:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)];
    }
    [self.thirdPartyAnswerView configureViewForThirdPartyObject:对象forViewStyle:TCThirdPartyAnswerViewStyleSearchCell];
}

最后我看来配置是这样的:

   - (无效)configureViewForThirdPartyObject:(TCTPOPlace *)对象forViewStyle:(TCThirdPartyAnswerViewStyle){风格
    self.titleLabel.text = object.name;
    self.addressLabel.text = [的NSString stringWithFormat:@%@%@,%@,object.address,object.city,object.state]
    self.ratingsLabel.text = [的NSString stringWithFormat:@%d个等级,object.reviewCount]
    * NSString的ratingImageName = [的NSString stringWithFormat:@。yelp_star_rating _%1f.png,object.rating]
    *的UIImage = ratingsImage [UIImage的imageNamed:ratingImageName];
    如果(ratingsImage){
        self.ratingImageView.image = ratingsImage;
    }
    如果(object.imageUrl){
        [self.thumbnailImageView setImageWithURL:[NSURL URLWithString:object.imageUrl]完成:无];
    }
}

一类的解决方案,但我不明白为什么


  1. 我的子视图被设计为320宽度,但对宽度没有自己的约束

  2. 的子视图加入到细胞,但看起来像该水平约束条件:

    • @| [_thirdPartyAnswerView] -33- |


  3. 的观点正在加入细胞后,立即配置,意为titleLabel文本设置正确的话。

  4. 无论出于何种原因,对文本布局,如果认为有充分的320,而不是282。

  5. 标签从未更新,即使子视图的帧被更新为282,并有在标签上的约束,将保持其正确的尺寸。

  6. 在厦门国际银行更改视图的大小是固定的282的问题,因为标签已开始与正确的大小。

我仍然不明白为什么标签不重新铺陈父视图的大小之后,它同时具有前端和后端的限制将被更新。

解决

请参见下面马特的答案是: http://stackoverflow.com/a/15514707/287403

如果你不看评论,主要的问题是,我在一个更大的宽度比设计视图时,被不知不觉地设置 preferredMaxLayoutWidth 通过IB它将被显示(在某些情况下)。 preferredMaxLayoutWidth 是用来确定文本换。因此,即使我的观点和titleLabel正常大小时, preferredMaxLayoutWidth 仍处于旧值,并且在意外造成分包装。设置而不是它的自动大小(⌘=在IB)的titleLabel,并更新 preferredMaxLayoutWidth 动态地 layoutSubviews 调用super之前是关键。感谢马特!


解决方案

我是人谁曾撰文指出,在一个表中的单元拥有不同的高度,这里的标签根据自己调整使用了5个标签自动布局单元格中的一个应用程序什么是在他们里面,它的工作。我要建议的,因此,您遇到问题的原因可能是你的约束下确定的布局 - 也就是说,你已经有了暧昧的布局单元格的元素。我不能检验这一假设,因为我看不到你的约束。但是你可以很容易地检查(我认为)用 PO [一个UIWindow keyWindow] _autolayoutTrace] 暂停在调试的时候。

另外,我有一个建议,其他(抱歉在你刚才扔的东西):确保你设置标签的 preferredMaxLayoutWidth 。这是至关重要的,因为它的宽度,其中标签将停止增长的水平和垂直方向开始越来越多。

I have a uilabel setup in a view. It doesn't have a width constraint, but its width is instead determined by a leading constraint to the thumbnail image, and a trailing constraint to the edge of the view.

The label is set to have 0 lines, and to word wrap. My understanding is that this should cause the frame of the uilabel to grow, and indeed it does sometimes. (Previous to auto layout, I would calculate and update the frame of the label in code).

So the result is, it works correctly in some instance and not others. See most cells working correctly there, but the last cell appears to be too big. In fact it's the right size. The title "Fair Oaks Smog Check Test" actually ends with "Only". So my calcuation for the cell size is right, it should be that size. However the label doesn't wrap the text for whatever reason. It's frame width does not extend off to the right, so that's not the issue.

So what is going on here? It's 100% consistent, always on that cell and not the ones above it, which makes me think it's related to the size of the text, and UILabel isn't re-laying out the text once this view is added to the cell (which makes it actually smaller width wise).

Any thoughts?

Some additional information

The height of the cells is calculated from one sample cell I create and store in a static variable:

- (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];
}

I configure the cell with my data object on the fly, and then call a method I have on it which calculates the height of the cell with a given table width (can't always rely on the cell frame being correct initially).

This in turn calls a height method on my view, since it is really where the label lives:

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

This method determines the height by figuring out the correct width of the label, and then doing a calculation:

- (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;
}

This works 100% correctly.

The cells are created obviously in cellForRowAtIndexPath and immediately configured:

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

In configuration of the cell, my view is loaded from a nib (it's re-used elsewhere, which is why it's not directly in the cell). The cell adds it as follows:

- (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];
}

Finally my view configuration looks like this:

- (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];
    }
}

A sort of solution, but I don't understand why

  1. My subview was designed at 320 width, but has no constraints of its own for width
  2. The subview was added to the cell, but with horizontal constraints that look like this:
    • @"|[_thirdPartyAnswerView]-38-|"
  3. The view was configured immediately after being added to the cell, meaning the text for the titleLabel was set right then.
  4. For whatever reason, the text was laid out as if the view had the full 320 instead of 282.
  5. The label was never updated, even though the frame of the subview was updated to 282, and there were constraints on the label that would keep it sized correctly.
  6. Changing the size of the view in the xib to be 282 fixed the issue, because the label has the right size to begin with.

I'm still not understanding why the label doesn't re-lay out after the size of the parent view is updated when it has both leading and trailing constraints.

SOLVED

See Matt's answer below: http://stackoverflow.com/a/15514707/287403

In case you don't read the comment, the primary problem was that I was unknowingly setting preferredMaxLayoutWidth via IB when designing a view at a bigger width than it would be shown (in some cases). preferredMaxLayoutWidth is what is used to determine where the text wraps. So even though my view and titleLabel correctly resized, the preferredMaxLayoutWidth was still at the old value, and causing wrapping at unexpected points. Setting the titleLabel instead to it's automatic size (⌘= in IB), and updating the preferredMaxLayoutWidth dynamically in layoutSubviews before calling super was the key. Thanks Matt!

解决方案

I'm someone who has written an app that uses autolayout of five labels in a cell in a table whose cells have different heights, where the labels resize themselves according to what's in them, and it does work. I'm going to suggest, therefore, that the reason you're having trouble might be that your constraints are under-determining the layout - that is, that you've got ambiguous layout for the elements of the cell. I can't test that hypothesis because I can't see your constraints. But you can easily check (I think) by using po [[UIWindow keyWindow] _autolayoutTrace] when paused in the debugger.

Also I have one other suggestion (sorry to just throw stuff at you): make sure you're setting the label's preferredMaxLayoutWidth. This is crucial because it's the width at which the label will stop growing horizontally and start growing vertically.

这篇关于的UILabel不能正确文本换行有时(自动布局)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆