5

サブビューのサイズに応じて UITableView 行に必要な高さを計算する方法については、SO やの場所に多くの良い情報があります。ここで適用している典型的な例は、可変長テキストのラベルを含むセルです。

ここに画像の説明を入力

通常のアドバイスはsizeWithFont:constrainedToSize:lineBreakMode:、テーブルビューの でを使用することheightForRowAtIndexPath:です。しかし、私が見たほとんどの例では、ラベルの既知の幅に基づいた「マジック」ナンバーを使用しています。

CGSize constraint = CGSizeMake(224.0, MAXFLOAT); //224 is known to be the width available
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];

いくつかのより良い例では、テーブルビューの境界を使用してから、セル内の他のビューのマジック ナンバーまたは定数を減算します。これは、少なくとも少し明確です (また、境界が回転などで変化する場合はより適切に機能します)。

CGSize constraint = CGSizeMake(self.tableview.bounds.size.width - 20 - 10 - 36 - 20, MAXFLOAT); //each non-label width subtracted
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];

これは一般的なアプローチですが、欠けているようです。他のセル サブビューの幅、さらにはフォントが変更されないことが保証されている (または常に両方の場所で常に変更される) と誰が言えますか?

この高さを提供する責任をセルに持たせたいと思いました。セルは常にその属性を認識しています。これを実現するために、まず、セル内のすべてのレイアウト コードでいくつかのローカル定数を参照するようにしました。次に、クラス メソッドをカスタム セル クラスに追加しました。このメソッドは、独自のフォントとサイズ定数に基づいて、特定のテキストに必要な高さを返すことができます。

+ (CGFloat)heightRequiredForText:(NSString *)text usingWidth:(CGFloat)width
{
    //a class method that tells the caller how much height is needed for the provided text, based on the cell's size and font constants
    CGSize constraintSize = CGSizeMake(width - kMargin - kGap - kMargin - kCheckboxWidth, MAXFLOAT);
    CGRect bounds = [text boundingRectWithSize:constraintSize
                                                options:NSStringDrawingUsesLineFragmentOrigin
                                             attributes:@{NSFontAttributeName:self.labelFont}
                                                context:nil];
    return bounds.size.height;
}

これにより、UITableViewController は単純にテキストと現在の境界の幅 (つまり、テーブルビューの幅) を提供できます。フォントとレイアウトは cell サブクラスで変更でき、すべてが「そのまま機能」し続けます。

質問1

補足として、これは合理的ですか?同じことを達成するためのより良い方法はありますか?

質問2

これが、この(そしてより標準的な)アプローチで私が抱えている主な問題です。セルが編集モードの場合、ラベルの幅は編集アクセサリに対応するように変更されます。行の高さは一定で、ラベルは自動レイアウトを使用しているため、高さが増加します。

ここに画像の説明を入力

必要な動作は、ラベルの高さを一定に保つことであり、必要に応じて切り捨てを使用する必要があります。

これをどこでどのように実装できますか? セルの setEditing: で何かをする必要がありますか? 高さを制限する別の制約を追加し、切り捨てをオンにして、編集時に反対を適用する == NO? 「スワイプして削除」パターンはどうですか - これは setEditing をトリガーしないと思いますか? layoutSubview はどうですか - そこで何かできますか?

4

1 に答える 1

1

私は多くのことを試しました-私が得た最も近いものは、layoutSubviewsをオーバーライドし、ユーザーが編集モードに切り替えたかどうかをテストし、そうであれば最初にラベルの固有の高さをキャプチャしてから、それを強制する一時的な制約を追加しました(その後削除されました)編集モードから抜けます)。いくつかのエッジケースを除いて、うまく機能しました。

しかし、その後、自動レイアウトについてもう少し考え始めました。私は何を達成しようとしていましたか?ラベルの幅を狭めたときに、ラベルの高さが大きくなりたくありませんでした。これは非常に単純な制約です。

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.label
                                                                    attribute:NSLayoutAttributeHeight
                                                                    relatedBy:NSLayoutRelationLessThanOrEqual
                                                                       toItem:self.contentView
                                                                    attribute:NSLayoutAttributeHeight
                                                                   multiplier:1
                                                                     constant:0]];

この追加の制約を追加するとうまくいきます。また、編集時に改行モードを切り捨てに切り替えることに注意してください。

ここに画像の説明を入力

于 2013-08-20T22:57:45.220 に答える