22

NSSplitViewサブビュー内で自動レイアウト制約を使用するにはどうすればよいですか?

私のNSSplitViewサブビューには 3 つの subview:topPanetableContainerありbottomPane、次のように制約を設定します。

NSDictionary* views = NSDictionaryOfVariableBindings(topPane, tableContainer, bottomPane);

for (NSView* view in [views allValues]) {
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
}

[myView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topPane(34)][tableContainer][bottomPane(24)]|"
                                                               options:0 
                                                               metrics:nil 
                                                                 views:views]];

[mySplitView addSubview:myView];

そして、コンソールでこれを取得しました:

Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>",
    "<NSLayoutConstraint:0x7fd6c4b30910 V:[CPane:0x7fd6c4b2f870(34)]>",
    "<NSLayoutConstraint:0x7fd6c4b30770 V:|-(0)-[CPane:0x7fd6c4b2f870]   (Names: '|':NSView:0x7fd6c4b22e50 )>",
    "<NSLayoutConstraint:0x7fd6c4b212f0 V:[CPane:0x7fd6c4b2fd10]-(0)-|   (Names: '|':NSView:0x7fd6c4b22e50 )>",
    "<NSLayoutConstraint:0x7fd6c4b2f910 V:[CPane:0x7fd6c4b2f870]-(0)-[NSScrollView:0x7fd6c4b234c0]>",
    "<NSLayoutConstraint:0x7fd6c4b21290 V:[CPane:0x7fd6c4b2fd10(24)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>

これが原因だと思います<NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]>が、自動サイズ変更マスクを設定しているため、リセットできませんNSSplitView

分割ビュー内で自動レイアウトを使用する最良の方法は何ですか? そして、自動レイアウトなしで分割ビューサブビューの最小/最大サイズを処理する方法はありますNSSplitViewDelegateか?

4

9 に答える 9

7

ウィンドウにツールバーがあり、このデリゲート メソッドのいずれかで分割ビューを制御 すると、このエラーが表示されることがわかりました。

splitView:constrainMinCoordinate:ofSubviewAt:   
splitView:constrainMaxCoordinate:ofSubviewAt:
splitView:shouldAdjustSizeOfSubview:

解決策は、windowDidLoad でツールバーをウィンドウにアタッチすることで見つかりました。

于 2012-11-05T17:31:01.260 に答える
4

NSSplitView は最初から奇妙なものであり、すぐになくなっても驚かないでしょう。NSSplitView を AutoLayout で 1 か月間動作させようとして、ある絶望的な攻撃から別の攻撃へと沈んでいった後、私はついにあきらめました。

私の解決策は、AutoLayout で NSSplitView をまったく使用しないことです。したがって、Autolayout なしの NSSplitView または NSSplitView なしの Autolayout のいずれか: これは思ったほど複雑ではありません: サブビューを並べて配置し、 as を追加するNSLayoutConstraintsだけIBOutletsです。これらの制約の定数は、コードでコントローラーから設定および変更できます。そのアプローチを使用すると、原点 (ウィンドウからスライドさせるための負のオフセット)、幅、および他のサブビューとの関係を設定できます。さらに、ビューのアニメーターを使用して制約を簡単にアニメーション化できます (NSSplitView をアニメーション化しようとしたことがありますか?)

欠けているのはディバイダーでのマウス ドラッグだけですが、これは、カスタム "SplitView" で mouseEvents を追跡する 2 行で実装できます。

Apple からの自動レイアウト「分割ビュー」の例 (残念ながら垂直のみ) があり、最近 github で少なくとも 1 つの新しいプロジェクトを見てきました。私にとっては、非常に普遍的なものを作成しようとするよりも、アプリの特定のニーズに合わせてカスタム ソリューションからやり直す方が簡単だと思いました (したがって、処理が複雑になりすぎます)。

編集:サブビューを別々のニブからロードするカスタムsplitViewを完成させました。制約の問題も自動レイアウトの警告もありません。NSSplitView で動作させるために 1 か月を費やしたのと比較して、制約に基づいて動作するカスタム splitView ができました。簡単にアニメーション化でき、たった 1 晩で作成されました。私は間違いなくこのルートを取ることをお勧めします!

于 2012-08-18T02:01:20.220 に答える
4

将来これに出くわし、制約ベースの置換へのジャンプスタートを探している人のために、自動レイアウトを使用して機能のNSSplitView一部を再作成しようとする小さなプロジェクトをここに書きました:NSSplitView

https://github.com/jwilling/JWSplitView

多少バグがありますが、このルートに進みたい人にとっては参考になるでしょう。

于 2012-12-20T02:39:21.093 に答える
3

10.8 ではその問題が修正されました。リリース ノートを参照してください。

これが10.7(カスタム分割ビュー)の私のソリューションです: https://github.com/benuri/HASplitView.git

于 2012-10-16T15:04:16.200 に答える
1

まったく無効にしたくありませんtranslatesAutoresizingMaskIntoConstraints。システム ビューの制約をいじってはいけません。NSSplitView個々のビュー自体のサイズ変更を処理し、本質的にそのコントロールを取り除こうとしています。言うまでもなく、スプリッターを説明するのを忘れていました。

分割ビューで最小または最大 (または定数) の幅/高さを設定する正しい方法は、それらをビューに個別に設定することです。特に、コードでこれを行う場合は、constraintWithVisualFormat への 2 つの個別の呼び出しを使用する必要があります。そうしないと、ビジュアル フォーマット言語がビュー間に制約を作成するためです。

これらすべてを IB で問題なく実行できます。分割ビューの各ビューの優先度を設定することもできます。これにより、サイズ変更が均等に分散されるのではなく、ウィンドウのサイズが変更されたときに、いずれかのビューのサイズが変更されます。

于 2012-08-17T14:58:58.543 に答える
0

私はこのクラスを回避策として使用しました。完全ではありませんが (サブビューが少し途切れます)、ブロックを解除しました。このクラスを各分割ビュー ペイン内のカスタム クラスとして使用します。

@interface FBSplitPaneView : NSView

@end

@implementation FBSplitPaneView

- (void)setFrame:(NSRect)frame
{
  for (NSView *subview in self.subviews) {
    subview.frame = self.bounds;
  }
  [super setFrame:frame];
}

@end
于 2015-04-22T19:23:42.450 に答える
0

反対するのは嫌いですが、Aucoの答えは最高に投票されるべきではありません. 十分な量の作業で問題を解決するのに、決して役に立ちません。私の意見では、NSSplitView はドキュメントを十分に読んでいない人にとってのみ問題でした。

ここで言及されている問題の実際の解決策はかなり単純です。自動レイアウトは、NSSplitView に新しい「Holding Priorities API」を導入しました。ドキュメントにあるように、サブビューの保持優先度に低い値を設定すると、幅が早くなる可能性が高くなります。これらはすべて IB で設定でき、絶望することなくプログラムで設定できます。作業時間:約20秒

于 2012-10-09T10:03:48.423 に答える
0

自動レイアウトから警告を取り除くのに少し時間がかかりましたが、IB (いくつかの分割ビューとサブビュー) で処理することができました。

私のレイアウトは次のようになります。

RootView
  |-- 1 番目の NSSplitView (3 つの垂直サブビュー)
      |----UIView (左)
      |---- 2 番目の NSSplitView (中央 & 2 つの水平サブビュー)
           |---UIView (上)
           |--- 3 番目の NSSplitView (下) & 3 つの垂直サブビュー)
               |---UIView (左)
               |---UIView (中央)
               |---UIView (右)
      |----UIView (右)

私の問題は、すべてのサブビューに 19 個の警告がありましたが、レイアウトが正常に見え、本来あるべきように機能したことでした。しばらくすると、警告の原因がわかりました。最初の分割ビューの外側のビューの制約です。

両方のビュー (左と右) には「幅 >= 200」の幅制約があり、中央のビュー (2 番目の分割ビュー) には制約がありませんでした (最小幅と最大幅がサブビューによって処理されるため)。

警告は、計算された最小幅がレイアウトよりも小さいため、自動レイアウトが IB-UI-Layout を縮小したいことを示しましたが、IB で縮小したくありませんでした。

最初の分割ビューの外側のサブビューの両方に固定制約「幅 = 200」を追加し、「ビルド時に削除」をチェックしました。

これで、レイアウトに警告がなくなり、すべてが正常に機能するようになりました。

私の結論

自動レイアウトと分割ビューの問題は、自動レイアウトがサブビューの幅制約を処理できないことだと思います。分割ビューを使用する理由は、ビューの動的な幅が必要であり、縮小と拡大の両方向で必要だからです。

したがって、 width <= xxx && width >= xxx はありません。Autolayout はそのうちの 1 つしか処理できず、IB で警告が表示されます。この問題は、実行前に削除される IB の一時的な制約で修正できます。

私が書いたことが理にかなっていることを願っていますが、私のプロジェクトではうまくいきました。

PS: このスレッドを見つけた今日まで解決策を見つけることができませんでした..だから、あなたの投稿が私にインスピレーションを与えたと思います:-)

于 2015-02-09T18:49:52.160 に答える
0

nibファイルとsetTranslatesAutoresizingMaskIntoConstraints:NOその後ですべてをロードします。

したがって、最初に[mySplitView addSubview:myView];ビューで追加し、その後自動サイズ変更マスクの制約への変換を無効にしてから、制約を に追加する必要がありますmyView

編集:

わかりました、myView を誤解しているようです。分割ビューではなく、サブビューに制約を追加する必要があります。

[topPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topPane(34)]" options:0 metrics:nil views:views]];

[bottomPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomPane(24)]" options:0 metrics:nil views:views]];

NSSplitViewのサブビューは既に自動サイズ変更されているため、エッジ制約 (「V:|[topPane(34)]」の「|」) を追加する必要はありません。

これにより、たとえば topPane 制約が次のようになります。

スクリーンショット

注: サブビューの内容は無視してください。これらは単なるプレースホルダーです。

于 2012-07-15T12:43:57.473 に答える