ビューにuilabelを設定しています。幅の制約はありませんが、代わりに、サムネイル画像の先頭の制約と、ビューの端の末尾の制約によって幅が決定されます。
ラベルは0行に設定され、ワードラップに設定されています。私の理解では、これによりuilabelのフレームが大きくなるはずですが、実際に大きくなることもあります。(自動レイアウトの前は、コードでラベルのフレームを計算して更新していました)。
その結果、ある場合には正しく機能し、他の場合には正しく機能しません。ほとんどのセルがそこで正しく機能しているのを確認してください。ただし、最後のセルは大きすぎるようです。実際、それは適切なサイズです。「FairOaksSmogCheck Test」というタイトルは、実際には「Only」で終わります。だから私のセルサイズの計算は正しいです、それはそのサイズでなければなりません。ただし、ラベルは何らかの理由でテキストを折り返しません。フレーム幅が右に伸びていないので、問題ありません。
では、ここで何が起こっているのでしょうか。100%一貫性があり、常にそのセル上にあり、その上のセルではないため、テキストのサイズに関連していると思います。このビューがセルに追加されると、UILabelはテキストを再レイアウトしません(実際には幅が狭くなります)。
何かご意見は?
いくつかの追加情報
セルの高さは、静的変数に作成して保存した1つのサンプルセルから計算されます。
- (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のテキストがその時点で設定されました。
- 何らかの理由で、テキストは、ビューが282ではなく320でいっぱいであるかのようにレイアウトされました。
- サブビューのフレームが282に更新されたにもかかわらず、ラベルが更新されることはなく、ラベルには正しいサイズを維持するための制約がありました。
- xibのビューのサイズを282に変更すると、ラベルのサイズが適切であるため、問題が修正されました。
親ビューのサイズが更新された後、先頭と末尾の両方の制約がある場合にラベルが再レイアウトされない理由はまだわかりません。
解決済み
以下のマットの答えを参照してください:https ://stackoverflow.com/a/15514707/287403
コメントを読まない場合の主な問題はpreferredMaxLayoutWidth
、表示されるよりも広い幅でビューを設計するときに、知らないうちにIBを介して設定していたことです(場合によっては)。preferredMaxLayoutWidth
テキストがどこで折り返されるかを決定するために使用されるものです。そのため、ビューとtitleLabelのサイズが正しく変更preferredMaxLayoutWidth
されていても、は古い値のままであり、予期しないポイントで折り返しが発生していました。代わりにtitleLabelを自動サイズ(IBでは⌘=)に設定し、 superを呼び出す前preferredMaxLayoutWidth
に動的に更新するlayoutSubviews
ことが重要でした。ありがとうマット!