概要
横幅は端末の画面幅にして縦にだけスクロールする画面を作りたいことは、iOSアプリ開発時によくあると思います。StoryboardのUIViewControllerにUIScrollViewを貼り付けてぱぱっと作りたいところですが、Autolayout,Size Classesを使ったStoryboardで実現するのはなかなか難しいのです。
これを作ることができたので、手順を紹介します。
対象はiOS7/8,Xcode6です。
Size Classesはw:ANY、h:ANYのみを想定しています(たぶん別の指定でもいけるけど)。
ちなみにObjective-Cなりswiftなりでコードを書けばこの方法を使う必要はないです。Storyboardだけでやりたいよという話。
難しいのか
-
普通に貼り付けると:StoryboardのUIViewControllerにUIScrollViewを貼り付けると、contentSizeが貼り付けたサイズになります。Size Classesがw:ANY,h:ANYでUIViewControllerいっぱいに貼り付けると、contentSizeが(600,600)固定になります。実行すると、縦にも横にもスクロールする画面になってしまいます。
-
プロパティcontentSizeを指定すると:User Defined Runtime AttributesからプロパティとしてcontentSizeを指定してはどうかというと、その場合横幅が固定になってしまいます。横幅は、端末ごとに異なる画面の幅にしたいところです。
手順
縦が1200pt、横が画面の横幅となるUIScrollViewを作ってみます。キモは、UIScrollViewの下にUIViewを配置することと、ConstraintにEqual Widthを指定することです。
(1). Storyboardを開き、UIViewControllerを貼り付けてください。そのUIViewControllerのViewを削除して、代わりにUIScrollViewを貼り付けます。さらにUIScrollViewにUIViewを貼り付けます。大きさはUIViewControllerいっぱいに。Size Classesはw:ANY, h:ANYにしてください。
UIScrollViewの背景色はグレー、Viewの背景色はオレンジにしてみました。
(2). Scroll ViewとViewの両方を選択し、Add New Constraintsを表示します。表示したら"Equal Widths"をチェックして、Addボタンを押してください。
ツリーに制約が1つ追加されます。
(3). Viewを選択してください。つづけて制約を追加します。
まず高さを指定します。ここではスクロールの縦幅として1200ptにします。ScrollViewの下のViewのWidth,HeightがスクロールのcontentSizeとなるので、先ほどのEqual Widthと併せてスクロールするサイズを指定したことになります。
ついでに、Viewのプロパティを開いてframeのサイズも1200ptにします。これをやらないと、あとでInterfaceBuilderで全体が表示されません。
さらにViewに上下左右(Top,Bottom,Leading,Tailing)の制約を追加します。NeighborがScroll Viewになっているかチェックしてください。この手順でやるとBottomがBottom Layout GuideになっているのをScroll Viewに変更する必要があります。Constrain to marginsのチェックはお好みで外してください。
これで計6個の制約がつきました。これでScrollViewが出来上がりです。
(4). あとは、見やすいように幾つかオブジェクトを追加しましょう。そのまえに今のInterfaceBuilderでは600,600しか画面が見えないので、縦1200ptまで見えるようにしましょう。
ViewControllerを選択して、Simulated SizeをFreeformにし、Heightを1200にします。Widthも600では見づらいので400にしました。
縦にながーいViewControllerが表示されたと思います。あとは適当にオブジェクトを配置します。黄色いオブジェクトは画面幅に合わせて広がるよう左右に制約をつけてみました。
(5). シュミレータで実行するとこうなります。
iPhone4sのシュミレータ縦。キャプチャは上にドラッグしています。縦スクロールバーが表示されているのがわかるでしょうか。
横。やはり縦にのみスクロールします。黄色いオブジェクトは左右の制約に従って横幅が広がっています。
作成したStoryboardはこちら
https://gist.github.com/hirobe/dbcb8fc56c357201935a
備考
StoryboardではUIScrollViewのcontentSizeが中のViewに依存するため、縦幅については中のViewの制約で固定しているのでそれになり、横幅については中のViewの横幅をScrollViewの横幅と一致させることで、結果として端末の横幅になっている感じかなと思います。試行錯誤したらできたもので、この理屈が正しいかはよくわかりません。
参考
- http://codehappily.wordpress.com/2013/11/14/ios-how-to-use-uiscrollview-with-autolayout-pure-autolayout-approach-multiple-smaller-views/
- http://blog.jarinosuke.com/entry/auto-layout-best-practice
- https://speakerdeck.com/shoby/6-plus
- https://developer.apple.com/library/ios/technotes/tn2154/_index.html