291

iOS 8 で実行してUITableViewおり、ストーリーボードの制約から自動セルの高さを使用しています。

セルの 1 つに 1 つのセルが含まれており、UITextViewユーザー入力に基づいて縮小および拡大する必要があります。タップしてテキストを縮小/拡大します。

これを行うには、テキスト ビューに実行時制約を追加し、ユーザー イベントに応じて制約の定数を変更します。

-(void)collapse:(BOOL)collapse; {

    _collapsed = collapse;

    if(collapse)
        [_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
    else
        [_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];

    [self setNeedsUpdateConstraints];

}

これを行うときはいつでも、tableView更新でラップして呼び出します[tableView setNeedsUpdateConstraints]

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView setNeedsUpdateConstraints];
// I have also tried 
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.

[tableView endUpdates];

これを行うと、セルは拡張されます (そして、実行中にアニメーション化されます) が、制約の警告が表示されます。

2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 

(

    "<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",

    "<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-|   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
 )

Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>

388 は私の計算した高さです。その他の制約はUITextViewXcode/IB からのものです。

最後の1つは私を悩ませていUIView-Encapsulated-Layout-Heightます-最初にレンダリングされたときのセルの計算された高さだと思います-(私は自分のUITextView高さを>= 70.0に設定しました)しかし、この派生した制約がそれを却下するのは正しくないようですユーザー cnstraint を更新しました。

さらに悪いことに、レイアウト コードは高さの制約を破ろうとしていると言っていますが、そうではありません。セルの高さを再計算し、すべてが思いどおりに描画されます。

それで、NSLayoutConstraint UIView-Encapsulated-Layout-Heightそれは何ですか(自動セルサイズ設定のために計算された高さだと思います)、どうすればきれいに再計算するように強制できますか?

4

20 に答える 20

73

私は同様のシナリオを持っています: UILabel オブジェクトの行が数行ある、1 つの行セルを持つテーブル ビューです。iOS 8 と自動レイアウトを使用しています。

回転すると、システムで計算された行の高さが間違っていました (43.5 は実際の高さよりはるかに小さい)。次のようになります。

"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"

ただの警告ではありません。テーブル ビュー セルのレイアウトがひどいです。すべてのテキストが 1 つのテキスト行に重なっています。

次の行が私の問題を魔法のように「修正」することに驚いています(自動レイアウトは何も文句を言わず、画面に期待どおりの結果が得られます):

myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works

この行の有無にかかわらず:

myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem
于 2014-11-26T11:42:01.723 に答える
34

制約の値の 1 つに優先順位を指定することで、警告メッセージを破らなければならないと警告を発することができました (以下を参照"Will attempt to recover by breaking constraint")。優先度を より大きいものに設定している限り49、警告は消えてしまうようです。

私にとって、これは私の制約を変更することを意味し、警告はそれが壊れようとしたと言った:

@"V:|[contentLabel]-[quoteeLabel]|"

に:

@"V:|-0@500-[contentLabel]-[quoteeLabel]|"

実際、その制約の任意の要素に優先順位を追加することができ、それは機能します。どちらでも構いません。私のセルは適切な高さになり、警告は表示されません。ロジャー、あなたの例では、高さの値の制約@500の直後に追加してみてください(例: )。388388@500

これが機能する理由は完全にはわかりませんが、少し調査しました。NSLayoutPriority 列挙では、NSLayoutPriorityFittingSizeCompression優先度レベルがであるように見えます50。その優先度レベルのドキュメントには、次のように記載されています。

FittingSize メッセージをビューに送信すると、ビューのコンテンツに十分な大きさの最小サイズが計算されます。これは、その計算でビューをできるだけ小さくしたい優先度レベルです。かなり低いです。通常、この優先順位で制約を作成することは適切ではありません。高くなりたい、低くなりたい。

参照されたメッセージのドキュメントは次のとおりです。fittingSize

保持する制約を満たすビューの最小サイズ。(読み取り専用)

AppKit は、このプロパティをビューで使用可能な最適なサイズに設定します。これは、AppKit とそのサブビューが保持するすべての制約を考慮し、ビューをできるだけ小さくするという設定を満たすためです。このプロパティのサイズ値が負になることはありません。

私はそれ以上掘り下げていませんが、これが問題のある場所と関係があることは理にかなっているようです.

于 2014-11-21T20:23:34.643 に答える
9

制約を更新するようにテーブル ビューに通知する代わりに、セルをリロードしてみてください。

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];

[tableView endUpdates];

UIView-Encapsulated-Layout-Heightおそらく、その時点でのセルの制約に基づいて、初期ロード中にセルに対して計算されたテーブル ビューの高さです。

于 2014-08-08T16:35:28.737 に答える
6

別の可能性:

自動レイアウトを使用してセルの高さ (contentView の高さ、ほとんどの場合は以下のとおり) を計算する場合、および uitableview セパレーターがある場合は、セルの高さを返すためにセパレーターの高さを追加する必要があります。正しい高さを取得すると、自動レイアウトの警告は表示されなくなります。

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
   [sizingCell setNeedsLayout];
   [sizingCell layoutIfNeeded];
   CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
   return size.height; // should + 1 here if my uitableviewseparatorstyle is not none

}
于 2014-10-16T17:46:48.950 に答える
1

このバグで頭をかきむしるのに数時間費やした後、ようやく自分に合った解決策を見つけました。私の主な問題は、異なるセルタイプに複数のペン先を登録していたが、1 つのセルタイプに異なるサイズを許可したことでした (そのセルのすべてのインスタンスが同じサイズになるわけではありません)。そのため、テーブルビューがそのタイプのセルをデキューしようとしていて、たまたま異なる高さになったときに問題が発生しました。設定で解決しました

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

セルがそのサイズを計算するためのデータを持っているときはいつでも。私はそれができると思います

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

何かのようなもの

cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

お役に立てれば!

于 2016-06-28T21:53:56.547 に答える
1

私の場合、問題は、データに基づいて行を表示/非表示にUIStackViewする 内の垂直にありました。UITableViewCell自動サイズ変更セルを使用していますが、セル自体は常に正しい高さで正しく表示されていました。ログだけが に関する制約例外でいっぱいでしたUIView-Encapsulated-Layout-Height

の上下の制約の優先度を低く設定することで、この問題を解決しましたUIStackView(デフォルトの 1000 ではなく 999)。現在、制約の例外はなく、テーブルの外観と動作は同じです。

于 2021-02-18T09:30:09.010 に答える
1

コンテンツに合わせてテキストビューのサイズを変更し、高さの制約定数を結果の高さに更新すると、UIView-Encapsulated-Layout-Height制約の競合が修正されました。たとえば、次のようになります。

[self.textView sizeToFit];
self.textViewHeightConstraint.constant = self.textView.frame.size.height;
于 2014-10-01T13:23:09.150 に答える
0

次のようなメッセージを受け取っていました。

同時に制約を満たすことができません...
...
...
...
NSLayoutConstraint:0x7fe74bdf7e50 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fe75330c5c0(21.5)]
...
...
によって回復を試みます制約を破る NSLayoutConstraint:0x7fe0f9b200c0 UITableViewCellContentView:0x7fe0f9b1e090.bottomMargin == UILabel:0x7fe0f9b1e970.bottom

私は高さのカスタムUITableViewCellを使用しています。また、メソッドUITableViewAutomaticDimensionを実装しました。estimatedHeightForRowAtIndex:

私に問題を与えていた制約は、このようなものでした

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[title]-|" options:0 metrics:nil views:views];

制約をこれに変更すると問題は解決しますが、別の回答のように、必須にしたい制約の優先度が下がるため、これは正しくないと感じました:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6@999-[title]-6@999-|" options:0 metrics:nil views:views];

ただし、実際に優先度を削除すると、これも機能し、制約違反ログが取得されないことに気付きました。

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[title]-6-|" options:0 metrics:nil views:views];

|-6-[title]-6-|これは、との違いが何かについて少し謎|-[title-|です。しかし、サイズを指定することは私にとって問題ではなく、ログが取り除かれます。また、必要な制約の優先度を下げる必要はありません。

于 2016-03-11T17:22:34.317 に答える
0

TableView はデリゲートから indexPath のセルの高さを取得します。次に、からセルを取得しcellForRowAtIndexPathます:

top (10@1000)
    cell
bottom (0@1000)

if cell.contentView.height:0 //<-> (UIView-Encapsulated-Layout-Height:0@1000) top(10@1000) が (UIView-Encapsulated-Layout-Height:0@1000) と競合する場合、

それらの優先順位は 1000 に等しいため、UIView-Encapsulated-Layout-Heightの優先順位の下に最優先順位を設定する必要があります。

于 2015-11-06T03:55:59.543 に答える