我在视图中有一个 uilabel 设置。它没有宽度约束,但它的宽度由缩略图图像的前导约束和视图边缘的尾随约束确定。
标签设置为 0 行,并自动换行。我的理解是,这应该会导致 uilabel 的框架增长,而且有时确实会增长。(在自动布局之前,我会在代码中计算和更新标签的框架)。
所以结果是,它在某些情况下可以正常工作,而在其他情况下不能正常工作。看到大多数单元格在那里正常工作,但最后一个单元格似乎太大了。事实上,它的大小是合适的。标题“Fair Oaks Smog Check Test”实际上以“Only”结尾。所以我对单元格大小的计算是正确的,应该是那个大小。但是,无论出于何种原因,标签都不会包装文本。它的框架宽度没有向右延伸,所以这不是问题。
那么这里发生了什么?它是 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];
}
}
一种解决方案,但我不明白为什么
- 我的子视图设计为 320 宽度,但没有自己的宽度限制
- 子视图已添加到单元格中,但具有如下所示的水平约束:
@"|[_thirdPartyAnswerView]-38-|"
- 视图是在添加到单元格后立即配置的,这意味着 titleLabel 的文本是在那时设置的。
- 无论出于何种原因,文本的布局好像视图具有完整的 320 而不是 282。
- 标签从未更新,即使子视图的框架已更新为 282,并且标签上存在保持其大小正确的约束。
- 将 xib 中的视图大小更改为 282 可以解决此问题,因为标签的开头大小正确。
我仍然不明白为什么在父视图的大小更新后标签没有重新布局,因为它同时具有前导约束和尾随约束。
解决了
请参阅下面的马特回答:https ://stackoverflow.com/a/15514707/287403
如果您没有阅读评论,主要问题是我preferredMaxLayoutWidth
在设计宽度大于显示宽度的视图时(在某些情况下)是在不知不觉中通过 IB 设置的。preferredMaxLayoutWidth
用于确定文本换行的位置。因此,即使我的 view 和 titleLabel 正确调整了大小,它preferredMaxLayoutWidth
仍然是旧值,并导致在意外点处换行。将 titleLabel 设置为自动大小(IB 中的⌘=),并在调用 super 之前preferredMaxLayoutWidth
动态更新 in是关键。layoutSubviews
谢谢马特!