41

ビューに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];
    }
}

ある種の解決策ですが、理由がわかりません

  1. 私のサブビューは320幅で設計されていますが、幅に独自の制約はありません
  2. サブビューがセルに追加されましたが、次のような水平方向の制約があります。
    • @"|[_thirdPartyAnswerView]-38-|"
  3. ビューはセルに追加された直後に構成されました。つまり、titleLabelのテキストがその時点で設定されました。
  4. 何らかの理由で、テキストは、ビューが282ではなく320でいっぱいであるかのようにレイアウトされました。
  5. サブビューのフレームが282に更新されたにもかかわらず、ラベルが更新されることはなく、ラベルには正しいサイズを維持するための制約がありました。
  6. xibのビューのサイズを282に変更すると、ラベルのサイズが適切であるため、問題が修正されました。

親ビューのサイズが更新された後、先頭と末尾の両方の制約がある場合にラベルが再レイアウトされない理由はまだわかりません。

解決済み

以下のマットの答えを参照してください:https ://stackoverflow.com/a/15514707/287403

コメントを読まない場合の主な問題はpreferredMaxLayoutWidth、表示されるよりも広い幅でビューを設計するときに、知らないうちにIBを介して設定していたことです(場合によっては)。preferredMaxLayoutWidthテキストがどこで折り返されるかを決定するために使用されるものです。そのため、ビューとtitleLabelのサイズが正しく変更preferredMaxLayoutWidthされていても、は古い値のままであり、予期しないポイントで折り返しが発生していました。代わりにtitleLabelを自動サイズ(IBでは⌘=)に設定し、 superを呼び出す前preferredMaxLayoutWidthに動的に更新するlayoutSubviewsことが重要でした。ありがとうマット!

4

3 に答える 3

43

私は、セルの高さが異なるテーブルのセルで5つのラベルの自動レイアウトを使用するアプリを作成した人です。ラベルは、セルの内容に応じてサイズが変更され、機能します。したがって、問題が発生している理由は、制約がレイアウトを過小評価していること、つまり、セルの要素のレイアウトがあいまいであることが原因である可能性があることをお勧めします。あなたの制約がわからないので、その仮説を検証することはできません。po [[UIWindow keyWindow] _autolayoutTrace]しかし、デバッガーで一時停止したときに使用することで、簡単に確認できます(私は思います) 。

また、もう1つ提案があります(あなたに何かを投げて申し訳ありません):ラベルのを設定していることを確認してくださいpreferredMaxLayoutWidth。これは、ラベルが水平方向に成長を停止し、垂直方向に成長し始める幅であるため、非常に重要です。

于 2013-03-20T03:22:08.520 に答える
13

私は同じ問題を抱えていて、この回答からの提案を使用してそれを解決しました。UILabelのサブクラスに、次のコードを配置しました。

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

これがUILabelのデフォルトの動作ではない理由、または少なくともフラグを介してこの動作を有効にできない理由がわかりません。

レイアウトプロセスの途中でpreferredMaxLayoutWidthが設定されているのではないかと少し心配していますが、それを回避する簡単な方法はありません。

于 2013-11-13T18:29:11.560 に答える
0

また、コードのレイアウト制約に整数を渡していることを確認してください。

私の場合、いくつかの計算(たとえば、convertPoint:toView :)の後で、23.99999997のようなものを渡していたため、最終的に2行のラベルが1つのライナーとして表示されました(フレームは正しく計算されたようですが) 。私の場合、CGRectIntegralがうまくいきました!

丸め誤差はyaを殺す可能性があります:)

于 2017-10-20T13:58:58.197 に答える