2013-08-20 33 views
5

SOおよびelsewhereには、サブビューのサイズに応じてUITableViewの行に必要な高さを計算する方法に関する多くの情報があります。典型的な例と私がここで適用している例は、可変長テキストのラベルを含むセルです。可変長ラベル、テーブルビュー行の高さ、および自動レイアウト

enter image description here

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

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は、単にテキストと現在の境界幅、(テーブルビューのすなわち幅)を提供することを可能にします。セルのサブクラスでフォントとレイアウトを変更することができ、すべてが「仕事だけ」になります。

質問1

ちょうどサイドノートとして、これは理にかなって?同じことを達成する良い方法はありますか?質問2

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

enter image description here

必要な行動は、ラベルの高さを一定に維持すると切り捨てが必要なときに使用しなければならないためです。

どこでこれを実装できますか?セルのsetEditingで何かをしなければならないのですか?たぶん高さを制限するための別の制約を追加し、切り捨てを有効にします。 'スワイプを削除する'パターンはどうでしょうか?これによってsetEditingがトリガーされるとは思いませんか? layoutSubviewについては何かできますか?

+0

私はお勧めのアプローチは[プロトタイプセルインスタンス]を使用することです(http://stackoverflow.com/questions/13660004/retrieve-custom -prototype-cell-height-from-storyboard/14127936#14127936)のようなものです。 –

答えて

1

私はレイアウトサブビューをオーバーライドしていました。ユーザーが編集モードに切り替えたかどうかをテストしていました。最初にラベルの本来の高さをキャプチャしてから、編集モードから出るときに削除されました)。いくつかのエッジケースを除いてうまくいきました。

しかし、私はもう少しオートレイアウトについて考え始めました。私は何を達成しようとしていたのですか?私は幅が小さくなったときにラベルの背が高くなることを望んでいませんでした。これはかなり単純な制約です。

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

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

enter image description here

関連する問題