583

仲間の開発者、Interface Builder (Xcode 5 / iOS 7) で AutoLayout に問題があります。これは非常に基本的で重要なので、これがどのように適切に機能するかを誰もが知っておくべきだと思います。これが Xcode のバグである場合、重大なバグです。

したがって、このようなビュー階層があるときはいつでも問題が発生します。

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

UIScrollView には、たとえば、各辺から 50 ピクセル (問題ありません) などの厳密な制約があります。次に、UILabelにトップスペース制約を追加します(問題ありません)(ラベルの高さ/幅を固定することもできますが、何も変更しませんが、ラベルの固有のサイズのために不要になるはずです)

UILabel に末尾の制約を追加すると、問題が発生します。

例: 末尾のスペース: Superview Equals: 25

2 つの警告が表示されますが、その理由がわかりません。

A)スクロール可能なコンテンツのサイズのあいまいさ (スクロール ビューには、スクロール可能なコンテンツの高さ/幅があいまいです)

B)見当違いのビュー (予想されるラベル: x= -67 実際: x= 207

この最小限の例を、ダウンロードできる新しいプロジェクトで作成し、スクリーンショットを添付しました。ご覧のとおり、Interface Builder は、Label が UIScrollView の境界 (オレンジ色の破線の四角形) の外側にあることを想定しています。問題解決ツールを使用してラベルのフレームを更新すると、その場所に移動します。

注: UIScrollView を UIView に置き換えると、動作は期待どおりになります (ラベルのフレームは正しく、制約に従っています)。したがって、UIScrollView に問題があるか、何か重要なことを見逃しているようです。

IB で提案されているように、ラベルのフレームを更新せずにアプリを実行すると、それが本来あるべき場所に正確に配置され、UIScrollView がスクロール可能になります。フレームを更新すると、ラベルが見えなくなり、UIScrollView がスクロールしません。

助けてオビワン・ケノービ!なぜあいまいなレイアウトですか?見当違いの理由は?

ここからサンプル プロジェクトをダウンロードして、何が起こっているかを確認してみてください: https://github.com/Wirsing84/AutoLayoutProblem

Interface Builder の問題の図

4

34 に答える 34

1173

だから私はこのように整理しました:

  1. の中にaをUIScrollView 追加UIViewします(これを と呼ぶことができますcontentView);

  2. このcontentViewでは、上、下、左、右のマージンを 0 に設定します(もちろん からscrollView) superView水平方向と垂直方向にも中央揃えを設定します。

アップデート:

今日、Apple は私たちが何年も前に解決した問題に気付き (lol_face)、コンテンツ レイアウト ガイドフレーム レイアウト ガイドを の一部として提供していUIScrollViewます。したがって、次の手順を実行する必要があります。

  1. 同上;

  2. このcontentViewでは、上下左右の余白を 0 に設定して、スクロール ビューのコンテンツ レイアウト ガイドに固定します。

  3. の高さをFrame Layout GuidecontentViewの高さと同じに設定します。幅についても同じことを行います。

  4. 最後に、同じ高さの制約の優先度を250に設定します (ビューを垂直方向にスクロールする必要がある場合は、幅を水平方向にスクロールします)。

終了しました。

contentViewこれで、すべてのビューをそのに追加できます。contentSizeの は、scrollViewに従って自動的にサイズ変更されますcontentView

contentViewの最後のオブジェクトの下部からcontentViewのマージンまでの制約を設定することを忘れないでください。

于 2014-12-01T11:14:54.527 に答える
103

このエラーを追跡するのにしばらく時間がかかりました。最初は ScrollView のサイズを固定しようとしましたが、エラー メッセージには「コンテンツ サイズ」と明確に表示されています。ScrollView の上部からピン留めしたものはすべて、下部にもピン留めされていることを確認しました。そうすれば、ScrollView はすべてのオブジェクトと制約の高さを見つけることで、コンテンツの高さを計算できます。これにより、あいまいなコンテンツの高さが解決され、幅はかなり似ています...最初は、ほとんどの X が ScrollView の中央に配置されていましたが、オブジェクトを ScrollView の横に固定する必要もありました。iPhone6 の方が画面が広いかもしれませんが、「あいまいなコンテンツの幅」エラーが解消されるため、これは好きではありません。

于 2013-10-01T20:51:28.123 に答える
64

私の自問自答の質問UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone Sizes に対する答えです。

しかし、それはあなたのケースも完全にカバーします!

したがって、最も単純なケースの初期状態は次のとおりです。

  1. すべてのエッジに対する制約が 0 の scrollView
  2. 幅と高さの制約が固定された水平方向と垂直方向の中央に配置されたボタン
  3. そしてもちろん、迷惑な警告 Has ambiguous scrollable content widthHas ambiguous scrollable content height.

1

私たちがしなければならないことは、次のとおりです。

  • 2 つの追加の制約を追加します。たとえば、ビューの末尾および/または下部スペースに「0」を追加します (下のスクリーンショットの例を参照)。

重要:末尾および/または下部の制約を追加する必要があります。「一流」ではありません - それはうまくいきません!

2

この問題を修正する方法を示すサンプル プロジェクトで確認できます。

PS

ロジックによると、このアクションは「競合する制約」を引き起こすはずです。しかし、いいえ!

なぜそれが機能するのか、Xcode がどの制約がより優先されているかを検出する方法がわかりません (これらの制約の優先順位を明示的に設定していないため)。以下のコメントでなぜそれが機能するのか、誰かが説明してくれたらありがたいです。

于 2014-10-09T08:28:28.083 に答える
52

以下で説明するようUIViewに、のサブビューとしてを作成する必要があります。UIScrollView

  • UIViewController
  • UIView「メインビュー」
    • UIScrollView
      • UIView「コンテナ ビュー」
        • 【あなたのコンテンツ】

2 番目のステップは、UIScrollView制約を作成することです。これは、superView に対する上部、下部、先頭、および末尾の制約を使用して行いました。

次に、コンテナの制約を追加しましたUIScrollView。ここから問題が始まります。同じ制約 (上、下、先頭、末尾) を配置すると、ストーリーボードに警告メッセージが表示されます。

「あいまいなスクロール可能なコンテンツの幅があります」および「あいまいなスクロール可能なコンテンツの高さがあります」

上記と同じ制約を続行し、制約を追加するだけでEqual HeightEqual Widthコンテナビューではなくメイン ビューに関連します。つまり、Container View の制約はのスーパービューに関連付けられています。UIScrollViewUIScrollView

その後、ストーリーボードに警告が表示されなくなり、サブビューの制約を追加し続けることができます。

于 2014-10-29T21:20:40.700 に答える
16

遅れるかもしれませんが、次の解決策は、ストーリーボードを使用するだけで、コードを追加せずにこの種の問題を解決します。

コンテンツ ビューでは、先頭/末尾/上/下のスペースの制約を scrollview に設定する必要があります。これにより、次のようにコンテンツ ビュー frame が変更されません。ここに画像の説明を入力

もちろん、スクロール ビューがコンテンツ サイズを認識できるように、コンテンツ ビューに追加の制約を作成する必要があります。たとえば、固定の高さと中心 x を設定します。

お役に立てれば。

于 2015-01-16T13:37:25.263 に答える
5

Swift 4+ アプローチ:

1) UIScrollView の上下左右のマージンを 0 に設定する

2) UIScrollView 内に UIView を追加し、上、下、先頭、末尾のマージンを 0 ( UIScrollView margins に等しい) に設定します。

3) 最も重要な部分は、幅と高さを設定することです。高さの制約は優先度を低くする必要があります

private func setupConstraints() {

    // Constraints for scrollView
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    // Constraints for containerView
    containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

    let heightConstraint = containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
    heightConstraint.priority = UILayoutPriority(rawValue: 250)
    heightConstraint.isActive = true
}
于 2018-12-19T22:17:47.727 に答える
0

同じエラーが発生していました..次のことを行いました

  1. View(スーパービュー)
  2. ScrollView 0,0,600,600
  3. ScrollView 内の UIView : 0,0,600,600
  4. UIView には、画像ビュー、ラベルが含まれています

scrollView(2)、次に UIView(3) の先頭/末尾/上/下を追加します。

ビュー(1)とビュー(3)を選択して、高さと重量を等しく設定します..それで私の問題は解決しました。

私は役立つビデオを作りました:

https://www.youtube.com/watch?v=s-CPN3xZS1A

于 2015-07-23T12:30:39.717 に答える
0

私がしたことは、ここに示すように別のコンテンツ ビューを作成することです。

コンテンツ ビューは自由形式であり、すべてのサブビューを contentView に関連する独自の制約と共に追加できます。

UIScrollView がメイン ビュー コントローラーに追加されます。

プログラムで IBOutlet を介してリンクされている contentView をクラスに追加し、UIScrollView の contentView を設定します。

Interface Builder を介した ContentView を使用した UIScrollView

于 2015-07-08T04:05:21.657 に答える
0

Xcode 11+、Swift 5。

@WantToKnowの回答によると、私は問題を解決し、ビデオコードを用意しました

于 2019-12-11T06:27:19.720 に答える
0

Interface BuilderのサイズインスペクターでViewController(UIScrollViewを保持するもの)のサイズをフリーフォームに設定すると、すべてが機能するはずです。

含まれている UIViewcontroller の Interface Builder のサイズ インスペクターでのフリーフォーム設定

于 2017-02-14T23:13:02.833 に答える
0

[XCode 7.2 および iOS 9.2 でテスト済み]

ストーリーボードのエラーと警告を抑制したのは、スクロール ビューとコンテンツ ビュー (私の場合はスタックビュー)の固有のサイズをPlaceholderに設定することでした。この設定は、ストーリーボードのサイズ インスペクターにあります。そしてそれは言う - 設計時の固有のコンテンツサイズの設定は、Interface Builder での編集中のビューにのみ影響します。ビューには、実行時にこの固有のコンテンツ サイズはありません。

したがって、これを設定しても問題はないと思います。

注:ストーリーボードでは、スクロールビューのすべての端をスーパービューに固定し、スタックビューのすべての端をスクロールビューに固定しました。私のコードでは、スクロールビューとスタックビューの両方でtranslatesAutoresizingMaskIntoConstraintsを false に設定しました。また、コンテンツのサイズについては言及していません。スタックビューが動的に拡大する場合、ストーリーボードに設定された制約により、スタックがスクロール可能になります。

ストーリーボードの警告に腹が立ったので、警告を抑制するためだけに物事を水平方向または垂直方向の中央に配置したくありませんでした。

于 2016-01-06T09:18:12.340 に答える
0

スクロールビューの上から下まで連続した制約の行を作成する方法があることを確認する必要があります。[-XXX]

私の場合 (水平方向にスクロールするスクロール ビュー)、スクロール ビューの子ごとに幅と高さの制約を追加する必要もありましたが、Apple のテクニカル ノートには記載されていません。

于 2017-01-18T04:32:21.920 に答える