Interface BuilderでUIScrollViewを使用するにはどうすればよいですか?


95

これまではUIScrollViewプログラムで操作することでうまく使用してきましたが、Interface Builderでのみ設定することで機能させるのに苦労しています。

iPhoneアプリにシンプルな「概要」ページがあります。それは持っているUITextView私の他のアプリに、いくつかのアイコンやリンクを。これらのビューをすべてに追加UIScrollViewし、合計サイズが480を超えるように配置しました。アプリを起動すると、scrollviewは画面に収まるコンテンツのみを表示し、何もスクロールしません。

これをIBを介して完全に行うことは可能ですか、またはコードを介してcontentSizeを操作する必要がありますか?

回答:


130

UIScrollViewのcontentSizeプロパティを設定するのを忘れていました。奇妙なことに、これをInterface Builderから行うことはできません。このスクロールビューを管理しているビューコントローラーから行う必要があります。


42
うわー、なんとなくIBを無意味なものにしています...これでうまくいきました、ありがとう。
ジョージアームホールド2009

20
(0,0)にサブビューが1つしかないかどうかをチェックし、そのサブビューに基づいてcontentSizeを自動的に設定するUIScrollvViewのサブクラスを作成できます。
ステファンアレンツ2009

1
それは私がしばらくの間受け取った最高のアドバイスです。スクロールビューが機能しない理由を理解できず、contentSizeに関する情報がどこにも見つかりませんでした。ありがとう。
ドリューC

46
私はInterface BuilderでcontentSizeを設定する方法を理解しようとしていたところ、この議論が見つかりました。少なくとも私にとっては、Xcode 4.5では、「ユーザー定義のランタイム属性」を使用して、contentSizetype という名前のエントリを追加しSize、目的の値を設定することで設定できます。
nlogax 2012年

5
少なくともデフォルトの動作として、iOSがサブビューのサイズに基づいてスクロールビューのを自動的に設定contentSizeしないのはなぜかについて、私はまだ困惑しています。
aroth

113

Boby_Wanの答えは私に考えさせられ、Interface BuilderからUIScrollViewのcontentSizeを構成するための次の解決策を見つけました:

  1. を選択 UIScrollViewストーリーボードシーンでをます
  2. IDインスペクターに移動し、新しいユーザー定義のランタイム属性をます(+ボタンをクリックします)。
  3. 属性を変更する キーのパスにしますcontentSize
  4. 属性を変更する タイプを次のようにSize
  5. 今設定 {に所望のコンテンツ幅所望のコンテンツの高さ }

たとえば、値を{320、920}に設定すると、ユーザーはiPhoneで余分な画面全体を下にスクロールできます。

(私はxcode 4.3.3を使用していますが、プロジェクトのiOS展開ターゲットは5.1です)

最初にこれを行ったとき、次のエラーを受け取りました:

不正な構成:
     4.3
     MainStoryboard.storyboard より前のバージョンのXcodeでサイズタイプのユーザー定義ランタイム属性

このエラーが発生した場合も、簡単に修正できます。プロジェクトナビゲーターでストーリーボードを選択し、ファイルインスペクターを起動しますInterface Builder Documentセクションを見つけて展開します。開発用のドロップダウンがあります。これがに設定されていることを確認しますXcode 4.3


7
素晴らしい発見!PS:これがAppleができる最高のことだと私は驚いています。これは、Appleのスタッフでさえ、独自のツール(インターフェイスビルダー)を使用しないことを示していると思います:)。
アダム

素晴らしい、これはXcode 4.4で私にとってはうまくいきました。しかし、IBで「表示」できないスクロールビューの部分にボタンを配置するにはどうすればよいでしょうか。
Robert Atkins

1
うまくいきました。ポインタがまだ「画面」内にあるときにドラッグを解放する必要があります。そうしないと、開始したときにスナップされます。なんて痛みだ。
Robert Atkins

私はそのようにしてみましたが、エラー"this class is not key value coding-compliant for the key keyPath"が出ます私が間違っていることを助けてくれませんか?xamarin-ios-c#を使用していることに注意してください
SoftSan

25

Autolayout(iOS6 +)を使用すると、の設定を回避できますcontentSize。代わりに次の制約を設定します。

  1. スクロールビューの上部を一番上の子の上部に固定します。
  2. そして、一番下の子の一番下に一番下を固定します。

1
ありがとうございますcontentSize
-Xcode

18

Interface Builderのみを使用してそれを行うことができ、Identity Inspector(3番目のインスペクタータブ)に移動して、新しいUser Defined Runtime属性を追加します。

  • キーパス: contentSize
  • タイプ: サイズ
  • 値: {幅、高さ}

14

ストーリーボードUIScrollViewを離れずにスクロールを作成する方法があります:

  1. UIScrollViewストーリーボードでを選択し、サイズインスペクターに移動して、[ コンテンツインセット]セクションの[ ボトム]値(または変更する必要のあるその他の値)をコンテンツ領域の高さに変更します。
  2. 次に、IDインスペクターに移動して、新しいユーザー定義のランタイム属性を作成し(+ボタンをクリックして)、名前を付けcontentSizeます。入力するタイプは関係ありません(デフォルト値のままでもかまいません)。

これでUIScrollView作業は適切に行われますが、2番目のステップが必要な理由はわかりません(たまたま見つけました)。:(


下の値を何に変更しますか?
ザクダンス

コンテンツ領域の高さに変更します。動作するようで、ユーザー定義の「contentSize」属性に指定した値を上書きします。
リードエリス

はい、リード、正解です。下の値をコンテンツ領域の高さに変更する必要があります。これを反映するために、元の投稿を編集しました。ありがとうございました!
RoberRM 2015

4

私が過去に使用した1つのアプローチは、インターフェイスビルダーでスクロールビューを含むビューからスクロールビューをドラッグし、その実際のサイズをcontentSizeにしたいサイズに設定することです。

インターフェイスビルダーについて本質的に明らかではないのは、関連付けられていないビューをnibに格納できますが、nibが主に使用するメインビューの一部ではないということです。

スクロールビューを表示したいビューに、プレースホルダーとして使用するシンプルなUIViewを配置します。(これは単に場所を視覚的に設計できるようにするためです。ビュー全体を使用している場合は、この手順をスキップして、この回答の最後にある2番目のコードスニペットを使用できます)。

その後、スクロールビューにコントロールを入力して、希望どおりに視覚的にレイアウトできます。実行時にそれらにアクセスできるように、ビューコントローラー内にプレースホルダーとscrollviewプロパティの両方を指定します。

実行時、-(void)viewDidLoad

scrollView.contentSize = scrollView.frame.size;
scrollView.frame = placeholder.frame;
[placeholder.superview addSubView:scrollView];
[placeholder removeFromSuperview];

代わりに(プレースホルダーを使用しなかった場合):

CGRect f = self.view.frame;
scrollView.contentSize = f.size;
f.origin.x = 0;
f.origin.y = 0;
scrollView.frame = f;
[self.view addSubView:scrollView];

最後に、インターフェイスビルダーでスクロールビューを "失った"(デザイングリッドから消えるように閉じることができる)場合でも、慌てないでください。デザイングリッドの左側にあるオブジェクトリストでそれをクリックするだけです。


1
ありがとう-これはうまくいきました。また、プレースホルダービューとスクロールビューのYourViewController.hでIBOutletsを宣言し、それらをインターフェイスビルダーで接続する必要があります。そして最後に、dot.notationは3行目のxCodeで認識されなかったため、通常のメッセージ送信構文を使用しました。
jiy

心配ない。コードスニペットを投稿する場合、「正確な」コードがあらゆる状況で機能することを期待するのではなく、概念を取得するために使用できない危険が常にあります。
同期さ

これが私が実際に使っている方法です。このプログラムのサイズを変更する必要すらありません。それは意図された方法だと思います。それが唯一の本当の答えです。
user4951

外に描いたら、スーパービューに移動します。多田。
user4951

私は実際にスクラッチパッド用にシーンの外のいくつかのビューのデザインを使用し始めました。そのため、これとは関係のない状況でも、生活が非常に楽になります。この回答をありがとう。
ベンジャミン

4

Autolayoutを使用するXcode 4.5では、サイズインスペクターにコンテンツインセットセクションがありません。だから私はそれをユーザー定義のランタイム属性の下に追加する必要があり、それからうまくいきました。

「ユーザー定義のランタイム属性」に追加するのは、「Rect」タイプ(UIEdgeInsets、Rectと同じ入力を持つ)であり、{top、left}、{bottom、right}として定義されるkeyPath == contentInsetです。contentSizeは、スクロールビューウィンドウの領域のみを定義します。contentInsetはスクロール可能な領域を定義します。

これが同じ状況の誰かに役立つことを願っています。


UITextViewの場合は、「textContainerInset」keyPathを使用します
Dima Deplov

4

上記の回答の多くは、誤解を招く、または古くなっています。2017年の時点で(おそらくもっと早い段階で)、インターフェイスビルダー、自動的にサイズ変更されるコンテンツを含むスクロールビューをサポートしています。トリックは、XCodeがスクロールビューとその中のコンテンツとの間の制約に特別な非標準の意味を与えるということです。これらの「内向き」の制約は実際にコンテンツのサイズに影響を与えることはありません。

これは、たとえば、スクロールビューをマージンなしでメインビューの下部に固定し、スクロールビューのコンテンツをマージンなしでスクロールビューの下部に固定することもできますが、実際にはこれによってコンテンツは拡大されません。代わりに、コンテンツは自己決定サイズ(以下を参照)を取得し、これはスクロールビュー内のスクロール可能領域のサイズになります。

このように考える-スクロールビューへの制約のバインドには非対称性があります。スクロールビューから「外側」(親)の世界への制約は、通常どおりにスクロールビューのサイズと位置を決定します。ただし、スクロールビューの「内部」の制約は、コンテンツにバインドすることによって、スクロールビューのスクロール可能領域のサイズと位置を実際に設定しています。

制約を設定すると、XCodeは常に現在の間隔を提示し、競合する方法で内向きと外向きの制約を意図的に変更することは決してないため、これは完全に自明ではありません。しかし、それらは上記の意味を持つことができます。1つはスクロールビューのレイアウトを制御し、もう1つはスクロール可能なコンテンツ領域のサイズを制御します。

私はこれを偶然偶然見つけ、それがどのように機能するように見えるかを見て、それを完全に説明し、これに関するAppleのドキュメントソースを引用するこの記事に私を導きました:

https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

コンテンツの自己決定サイズに関する最後の重要な情報:通常は親ビューの幅などにコンテンツのサイズを設定しているため、ここでは問題が発生していると感じるかもしれませんが、この場合、親はスクロールビューであり、上記のとおり-制約はコンテンツサイズに影響しません。ここでの答えは、ビュー階層内で直接隣接していないアイテムにアイテムを制限できることを覚えておくことです。たとえば、コンテンツビューの幅をメインビューの幅に設定して、スクロールビューにそれを実行させるのではなく、無駄にしようとするあなたのために。


2

Interface Builderで任意のView Controllerの[Properties]アイコンをクリックすると、それをSimulated Metricsで「フリーフォーム」サイズに設定し、メインビューのサイズを目的のコンテンツサイズに変更できます。

これにより、ScrollViewのコンテンツを1つの大きなビューであるかのように作成できます。これはシミュレートされたメトリックのみであるため、ロードされると、View Controllerはウィンドウの境界に合わせてサイズ変更されます。


2

Interface Builderを介してUIScrollViewを設定することは直感的ではありません。これを設定するための私のチェックリストは次のとおりです。

  1. UIViewControllerのXIBファイルを選択します。インターフェースビルダーの「Identity Inspector」で、UIViewをクラスタイプUIScrollViewに変更します。

  2. [ファイルインスペクタ]で、[自動レイアウト]をオフにします

  3. [属性インスペクタ]で、サイズをフリーフォームに変更します。その後、手動でスクロールビューをストレッチするか、[サイズインスペクター]でカスタムの幅と高さを指定できます。

  4. 「Identity Inspector」で、タイプ「Size」の「contentSize」と呼ばれる新しいユーザー定義ランタイム属性を追加し、それを{320、1000}のような値に変更します。これをプログラムで設定することはできなくなったため、この手順が必要になるため、スクロールビューの内容がウィンドウよりも大きいことがスクロールビューに認識されます。


2

スクロールビューのautoLayoutを削除するだけです。コードは次のように簡単です。

scrollviewName.contentSize = CGSizeMake(0, 650);

.hファイルにibouletプロパティを作成し、.mファイルに合成するだけです。スクロールが有効になっていることを確認してください。


1

はい、st3fanは正しいです。UIScrollViewのcontentSizeプロパティを設定する必要があります。ただし、この目的で自動レイアウトをオフにしないでください。コードなしで、IBのautolayoutのみでUIScrollViewのcontentSizeを簡単に設定できます。

UIScrollViewのautolayout contentSizeを直接設定しない場合、UIScrollViewのすべてのサブビューの制約に基づいて計算されることを理解することが重要です。そして、必要なのは、両方向のサブビューに適切な制約を提供することだけです。

たとえば、サブビューが1つしかない場合は、高さとスペースを上から下からスーパービュー(つまり、この場合はscrollView)に設定できますcontentSize.heightは合計として計算されます

Vertical Space (aSubview.top to Superview.top) + aSubview.height + Vertical Space (aSubview.top to Superview.top)

contentSize.widthは、水平方向の制約から同様に計算されます。

contentSizeを適切に計算するための制約が少なすぎる場合は、ビューのコントローラーシーンアイテムの近くに小さな赤いボタンが表示され、レイアウトのあいまいさを通知します。

多くのサブビューがある場合、それは制約の「チェーン」である可能性があります。DanyalAytekinの回答のように、サブビュー間の最上部から最上位のサブビュー、高さとサブビュー間の最下部のサブビューとスペース。

しかし実際には、ほとんどの場合、必要なサイズの空のビューを追加し、scrollViewの上下左右のスペースを0に設定する方が便利です。 このビューは「コンテンツビュー」として使用できます。つまり、他のすべてのサブビューを配置できます。その上に、またはすでに多くのサブビューがあり、それらを移動してレイアウトを再度設定したくない場合は、この補助ビューを既存のサブビューに追加して非表示にすることができます。

scrollViewをスクロール可能にするには、計算されたcontentSizeをscrollViewのサイズより大きくする必要があります。


1

Autolayoutsを使用してStoryBoardでUIScrollViewを使用できます。基本的に必要なものは次のとおりです。

  1. UIScrollViewを追加
  2. すべての制約を追加します(上端、左端、右端、下端からのインセットなど)。
  3. 「コンテナー」UIViewをUIScrollViewに追加します。
  4. 1方向のスクロールだけ(たとえば、垂直方向)が必要な場合:高さを明示的に(たとえば、600)設定し、幅をUIScrollViewの幅にリンクします。
  5. 双方向スクロールが必要な場合は、幅と高さの両方を設定してください。

ストーリーボードの設定



0

もっと便利な方法を見つけます。

1:スクロールビューのサイズをスケーリングして、その中にすべてのUIを含めます。

2:スクロールビューのiboutletを追加します。

3:viewDidLoadで、スクロールビューのframe.sizeを保存します。
(例_scrollSize = _scrollView.frame.size;)

4:viewWillAppearで、前に保存したCGSizeでcontentSizeを設定します。
(例_scrollView.contentSize = _scrollSize;)

5:完了〜


0
  1. UIViewControllerを追加
  2. UIViewController 'Attribute Inspector-> Simulated Metrics'でフリーフォームのサイズを設定します
  3. UIViewController 'Size Inspector-> View Controller'で高さを800に設定します
  4. UIViewControllerにUIScrollViewを追加する
  5. すべての制約をUIScrollView(上、左、右、下)に追加し、配置X =中央を追加します。
  6. UIScrollViewにUIViewを追加する
  7. UIViewにすべての制約(上、左、右、下)を追加し、配置X =中央を追加します。はい、#3のUIScrollViewと同じですが、UIView
  8. UIViewに高さ制約を追加します。たとえば780
  9. 走る

ストーリーボード


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.