サブビューのサイズに応じて 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 はどうですか - そこで何かできますか?