web-dev-qa-db-ja.com

iOSでは、マージン、エッジインセット、コンテンツインセット、配置長方形、レイアウトマージン、アンカーなどの違いは何ですか?

IOSコミュニティでは、レイアウトに関していくつかの異なるオプション/用語と人々が使用しているようです(たとえば、UIEdgeInsetsはタイプですが、「インセットの設定」またはレイアウトマージンとレイアウトガイドの違いを聞く/読む)。

私は常に機能するオプションを見つけることができました。しかし、私はその仕事に適したツールを使用しているとは決して確信していません。

誰かがこれらのレイアウトのさまざまな側面と、それぞれを最良の方法でいつ使用するかを明確にする手助けをすることができますか?

28
kraeon

バウンティの提供者であること...私の混乱の大部分は、 UILayoutGuide クラスを適切に理解していないことが原因だと思います。それが鍵ですが、非常にシンプルでもあります。

最初に problem を紹介しましょう:

昔は、これらの円を次のように制限する必要がある場合:

enter image description here

次に、clearUIViewsを作成してサブビューとして追加し、以下のように制約を追加する必要がありました。

enter image description here


今日は、それらをサブビューとして追加する必要はありません。代わりに、単に

レイアウトガイドの作成

レイアウトガイドを作成するには、次の手順を実行する必要があります。

  1. 新しいレイアウトガイドをインスタンス化します。
  2. ビューのaddLayoutGuide(_:)メソッドを呼び出して、レイアウトガイドをビューに追加します。
  3. 自動レイアウトを使用して、レイアウトガイドの位置とサイズを定義します。これらのガイドを使用して、レイアウト内の要素間のスペースを定義できます。次の例は、一連のビュー間の等間隔を定義するために使用されるレイアウトガイドを示しています。

手順:

let space1 = UILayoutGuide()
view.addLayoutGuide(space1)

let space2 = UILayoutGuide()
view.addLayoutGuide(space2)

space1.widthAnchor.constraintEqualToAnchor(space2.widthAnchor).active = true
saveButton.trailingAnchor.constraintEqualToAnchor(space1.leadingAnchor).active = true
cancelButton.leadingAnchor.constraintEqualToAnchor(space1.trailingAnchor).active = true
cancelButton.trailingAnchor.constraintEqualToAnchor(space2.leadingAnchor).active = true
clearButton.leadingAnchor.constraintEqualToAnchor(space2.trailingAnchor).active = true

レイアウトガイドは、他の多くのビューやコントロールを含むブラックボックスとしても機能します。これにより、ビューの一部をカプセル化して、レイアウトをモジュール化したチャンクに分割できます。

3つの興味深いメモ:

  1. 「デバッグ階層の表示」を使用している場合は、UILayoutGuideのインスタンスがさらに表示されます。
  2. UIViewと同様に、UILayoutGuideinstanceにはall種類のアンカーがあります
  3. ダミーのUIViewを作成してUILayoutGuidesを作成するだけではない理由については、「ビューの階層にダミーのビューを追加するには、多くのコストがかかります。最初に、ビュー自体を作成して維持するコストがあります。2番目に、ダミーのビューは、ビュー階層の完全なメンバーです。つまり、階層が実行するすべてのタスクにオーバーヘッドを追加します。最悪の場合、非表示のダミービューは、他のビューを対象とするメッセージを傍受し、見つけるのが非常に難しい問題を引き起こす可能性があります。」

enter image description here

詳細については、 documentation を参照してください。


topLayoutGuidesafeAreaLayoutGuide

topLayoutGuide(非推奨)

これは非推奨ですが、学習目的のためです:UIViewControllerには2つのダミーボックスがあります。上部の1つのプロパティはtopLayoutGuideという名前で、下部の別のプロパティはbottomLayoutGuideという名前です。 viewController自体には、左側/先頭または右側/末尾のガイドはありません。これらは両方ともUILayoutGuideのインスタンスです

view.topAnchorに制限されている場合、つまり:

tableView.topAnchor.constraint(equalTo: view.topAnchor)

enter image description here tableViewは、navigationBarの下部から開始しません

topLayoutGuide.bottomAnchorに制限されている場合、つまり:

tableView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)

enter image description here tableViewは、navigationBarの下部から始まります

また、レイアウト設計によっては、コンテンツをナビゲーションバーの下にぼかしたい場合があります。

そして、あなたのコンテンツをエッジからエッジまで表示するという考えでした。そしてそれはバーを重ねるので、バーを介してコンテンツでこれらの素敵なカラフルなぼかしを得ることができます

詳細については、この WWDCの瞬間 とこの質問 here を参照してください。ソリューションは正確に関連しているとは思いません。問題の画像だけです。

safeAreaLayoutGuide

iOS11以降

AppleはtopLayoutGuideおよびbottomLayoutGuideを廃止しました。したがって、2つのダミーボックスを持つ代わりに、UIViewインスタンスに safeAreaLayoutGuide という名前のダミーボックスが1つあります。 UIViewControllerにはこれがなくなりました... useyourloaf からコピーされた視覚的な比較: enter image description here

補足:ストーリーボードを使用する場合、ビューをtopLayoutGuideまたはsafeAreaLayoutGuideの上に揃えると、同じようにレンダリングされます。ストーリーボードを使用しない場合(プログラムでそれを行う場合)、iOS11とLessThaniOS11の間で踊り、2つの異なるバージョンのコードを使用する必要があります。

safeAreaLayoutGuideの詳細については、 次のAppleの記事を設定することをお勧めしますhighly。コンテンツ相対配置安全なエリアへ

注:safeAreaLayoutGuideはUIViewプロパティです。 topLayoutGuideはUIViewControllerプロパティです。


layoutMarginsGuide

  • UIViewにはダミーボックスが1つしかありません。プロパティの名前はlayoutMarginsGuideです。ただし、UIViewControllerとは異なり、上部または下部にありません。それはちょうどUIViewへの8ポイントのパディング/インセット(== --- ==)で中央に座っているので、これはどこで役に立ちますか? : これは、textViewをUIViewインスタンスのエッジに制約するしない場合に使用します。これにより、読書体験が向上します。または、スーパービューのLeadingAnchorにボタンを制限して醜い外観にする代わりに、アンカーに8ポイントを追加します。つまり、ボタンをLeadingAnchorに制限してから、8つの定数ポイントを追加します。 取り消し線付きのテキストは、実際にreadableContentGuideを使用する場所です。layoutMarginsGuideは、ボタンまたはラベルが不要な場合に便利ですそのスーパービューの端に

    someButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8)
    

    しかし、もっと簡単な方法があります。 Appleの推奨マージンを使用してください。

    someButton.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor)
    

    documentation にある例も参照してください。良いRaywenderlichチュートリアルは here にあります


readableContentGuide

  • layoutMarginGuideとは少し異なります。どちらもUIViewのプロパティです。時々それらは同一である場合もあれば、そうでない場合もあります。その目的は次のとおりです。

    このレイアウトガイドは、ユーザーに頭を動かしてラインを追跡させることなく、簡単に読むことができる領域を定義します

    詳細については、 WWDCからのこの瞬間:アダプティブレイアウトの構築 およびこの素晴らしい useyourloafチュートリアル を参照してください。

    IPhone 7 Plusでは、縦向きでは、読みやすいコンテンツガイドはビューのマージンガイドと同じですが、横向きでは、テキストビューの両側に余白があります。 iPadの横向きでは、余白が大幅に増加します。

    マージンサイズは、システムの動的タイプによって異なります。フォントが大きいほど、ガイドの幅が広くなります。

    RayWenderlich から

下の画像では、シアンはlayoutMarginGuideに固定されていますが、グリーンはreadableContentGuideに固定されています。

enter image description here


UIEdgeInsets

layoutMarginsGuideを変更する場合、つまり、必要なマージンを8ポイントから16ポイントに変更する場合は、layoutMarginsの値を変更してから、layoutMarginsGuide 'sanchorsは自動的に更新されます。 UIEdgeInsetsは、layoutMarginstypeにすぎません。 layoutMarginsUIViewクラスのプロパティnameです

someview.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50)

このコードfound️が効果を発揮する唯一の場所はviewDidLayoutSubviews内です。詳細については、 こちら を参照してください


Anchors

これらは基本的なものですが、特別なものはありません。これらは、UIView/UILayoutGuideの最も遠いエッジです。 UIViewとUILayoutGuideの両方のインスタンスにそれがあります。 [〜#〜]すべて[〜#〜]制約は最終的にアンカーを使用して制約されます。これはtoの問題ですあなたがそれをアンカーしているものエンティティのアンカー。 safeAreaLayoutGuideのアンカー、layoutMarginGuideのアンカー、topLayoutGuideのアンカー、viewのアンカーのいずれかになります。 (heightAnchorを50に固定することもできるので、その場合、別のアンカーはありません)

layoutMarginsGuideAnchorsgreat視覚的比較は、この answerから見つけることができます 。ストーリーボードを使用して行われるため、理解が容易になります。


contentInsets

理解することは重要ですが、まったく異なる議論であり、他の人とは何の関係もありません。 UIScrollViewsに固有です。詳細については、 この素晴らしい記事 を参照してください


結論

安全ですべてがの内側であることを確認するには、ビューをsafeAreaLayoutGuideを使用します。システムが提供するマージンを使用してビューのレイアウトを改善したり、一部のパディングを追加したりする場合は、layoutMarginGuideを使用してください。読みやすくするには、readableContentGuideを使用します。

readableContentGuideのサイズは常にlayoutMarginGuide以下です。
layoutMarginGuideのサイズは常にsafeAreaLayoutGuideより小さいか等しい

layoutMarginsはCSSのパディングと非常に似ています。 safeAreaLayoutGuideはCSSマージンに似ています。 readableContentGuideに相当するCSSがあるかどうかわかりません


補遺:ContentInsetとcontentOffsetの比較

これらはscrollViews用であり、他の回答とは多少関係ありません。 contentInsetcontentOffsetについては、 WWDC 2018のこの瞬間:UIKit:Apps for Every Size and Shape をご覧ください。ビデオはとてもシンプルです。以下のKarthikの回答も参照してください。そうは言っても、scrollViewがどのように機能するかを完全に理解し、contentSizeが何であるかを理解することが重要です。そうでなければ、複雑になります。 contentSizeとscrollViewの詳細については、 Vacawamaの回答はこちらをご覧ください

27
Honey

次のリンク/写真から情報を得てください。

以下のリンクから、レイアウトパラメータに関する必要な情報を推測できます。

  1. 配置の四角形alignment rects.

  2. コンテンツインセットとオフセット例2content insetscontent offestanother example

  3. マージンmargins

5
Karthik Kumar

これが退屈な答えである場合は申し訳ありませんが、Apple開発者向けドキュメントは、各UIViewプロパティがどのように使用されることが意図されているかを説明するのにかなり優れていると思います。

機能する複数のメソッド/オプションがある場合にレイアウトを実装する最良の方法については...それは本当にスタイル/意見の問題です。次の基準に焦点を当てて決定を下します。

  1. 保守/デバッグ/理解が最も難しいオプションを排除することを検討してください
    • あなたのチームに新しく加わった誰か、またはあなたのコードを継承している誰かを想像してください-どの実装がデバッグが難しいでしょうか、そしてその理由は?
  2. レイアウトの再配置/展開/編集を困難にするオプションを排除することを検討してください
  3. アプリの他の部分と一致しないオプションを排除することを検討してください(この種は最初のポイントに戻ります)
  4. Appleの意図に反するオプションを排除することを検討してください(意図を理解するには、docs/WWDCの講演を参照してください)。

チームはこの基準を使用して協力し、各シナリオで「UIのレイアウト方法」について合意することができます。あなたが求めているのは、そのようなディスカッションの合計結果である、レイアウトスタイルのガイドです。

私の経験では、これは私が取り組んだチームで常に有機的に発展しており、実際には書き留められていませんでした。上記のポイント3のはるかに多くのことでした。


質問で説明されているクラスのAppleドキュメントからの抜粋:

オン ILayoutGuide

ユーザーインターフェイスでビュー間スペースまたはカプセル化を表すために作成したダミービューを置き換えるには、レイアウトガイドを使用します。従来、ダミービューを必要とする多くの自動レイアウト手法がありました。

...

UILayoutGuideクラスは、ダミービューによって以前に実行されたすべてのタスクを実行するように設計されていますが、より安全で効率的な方法で実行するように設計されています。

オン layoutMargins

IOS 11以降では、このプロパティの代わりにdirectionalLayoutMarginsプロパティを使用してレイアウトマージンを指定します。

オン directionalLayoutMargins

このプロパティを使用して、このビューのエッジとそのサブビューの間の望ましい間隔(ポイント単位)を指定します。先行マージンと後続マージンは、現在のレイアウト方向に基づいて、左マージンまたは右マージンに適切に適用されます。

オン contentInset

このプロパティを使用して、コンテンツとコンテンツビューの端の間のスペースを拡張します。サイズの単位はポイントです。デフォルト値はUIEdgeInsetsZeroです。

オン topAnchor

このアンカーを使用して、ビューの上端に拘束を作成します。このアンカーは、他のNSLayoutYAxisAnchorアンカーとのみ組み合わせることができます。詳細については、NSLayoutAnchorを参照してください。

オン NSLayoutAnchor

これらの制約を使用して、自動レイアウトを使用してプログラムでレイアウトを定義します。 NSLayoutConstraintオブジェクトを直接作成する代わりに、制約するUIView、NSView、またはUILayoutGuideオブジェクトから始め、そのオブジェクトのアンカープロパティの1つを選択します。これらのプロパティは、自動レイアウトで使用されるメインのNSLayoutConstraint.Attribute値に対応し、その属性に制約を作成するための適切なNSLayoutAnchorサブクラスを提供します。アンカーのメソッドを使用して、制約を作成します。

0
mattliu