ビューにUilabelのセットアップがあります。幅の制約はありませんが、その幅は代わりにサムネイル画像の先頭の制約と、ビューのエッジの末尾の制約によって決定されます。
ラベルは0行に設定され、ワードラップされます。私の理解では、これによりUilabelのフレームが成長するはずであり、実際に時々そうなることもあります。 (自動レイアウトの前に、コードでラベルのフレームを計算して更新します)。
結果は、ある場合には正しく機能し、他の場合には正しく機能しないことです。ほとんどのセルが正常に機能しているのを確認しますが、最後のセルが大きすぎるようです。実際、適切なサイズです。タイトル「Fair Oaks Smog Check 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];
}
データオブジェクトを使用してセルをオンザフライで構成し、指定されたテーブル幅のセルの高さを計算するメソッドを呼び出します(最初はセルフレームが常に正しいとは限りません)。
これは、実際にはラベルが存在する場所であるため、ビューのheightメソッドを呼び出します。
- (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];
}
}
@"|[_thirdPartyAnswerView]-38-|"
親ビューに先行制約と後続制約の両方がある場合、親ビューのサイズが更新された後にラベルが再レイアウトされない理由がまだわかりません。
以下のマットの答えを参照してください: https://stackoverflow.com/a/15514707/2874
コメントを読んでいない場合、主な問題は、表示されるよりも大きな幅でビューを設計するときに、IBを介してpreferredMaxLayoutWidth
を設定していることです(場合によって)。 preferredMaxLayoutWidth
は、テキストの折り返し位置を決定するために使用されるものです。そのため、私のビューとtitleLabelのサイズは正しく変更されましたが、preferredMaxLayoutWidth
はまだ古い値であり、予期しないポイントで折り返しが発生していました。代わりにtitleLabelを自動サイズ(IBでは⌘=)に設定し、superを呼び出す前にpreferredMaxLayoutWidth
でlayoutSubviews
を動的に更新することが重要でした。ありがとう、マット!
私は、セルの高さが異なるテーブル内のセルで5つのラベルの自動レイアウトを使用するアプリを書いた人です。セルの高さは異なります。したがって、あなたが問題を抱えている理由は、制約がレイアウトを決定していないこと、つまりセルの要素のレイアウトがあいまいであるためかもしれないことをお勧めします。私はあなたの制約を見ることができないので、その仮説をテストすることはできません。ただし、po [[UIWindow keyWindow] _autolayoutTrace]
デバッガーで一時停止したとき。
また、もう1つ提案があります(物を投げるだけで申し訳ありません):ラベルのpreferredMaxLayoutWidth
を設定していることを確認してください。これは、ラベルが水平方向に拡大を停止し、垂直方向に拡大を開始する幅であるため、重要です。
私は同じ問題を抱えていました この答え からの提案を使用してそれを解決しました。 UILabelのサブクラスにこのコードを配置しました。
- (void)layoutSubviews
{
[super layoutSubviews];
self.preferredMaxLayoutWidth = self.bounds.size.width;
}
これがUILabelの既定の動作ではない理由、または少なくともフラグを使用してこの動作を有効にできない理由はわかりません。
PreferredMaxLayoutWidthがレイアウトプロセスの途中で設定されることを少し心配していますが、それを回避する簡単な方法はありません。
また、コードでレイアウト制約に整数を渡していることを確認してください。
私にとっては、いくつかの計算(例:convertPoint:toView :)の後、23.99999997のようなものを渡しており、最終的には2行のラベルが1行として表示されます(フレームは正しく計算されているように見えました) 。私の場合、CGRectIntegralがトリックを行いました!
丸めエラーはyaを殺す可能性があります:)