LoginSignup
39
27

【Swift】UIStackViewをスクロールさせる

Last updated at Posted at 2018-12-12

投稿6回目。
最近はポケモンカードに夢中になってなかなか勉強できていません。
心改めて意識的に学習に取り組んでいきましょう。

本題です

StackView便利ですよね。レイアウト組むとき、制約つけるのなんか難しい><
ていう意識のある人にとっては、とっても重宝されるものかと思います。
自分もStackView大好きでよく使っているのですが、StackViewを使っていると「StackViewをスクロールさせたい」と思う場面があると思います。
スクロールといえばUIScrollViewですが、UIScrollViewていうのはそもそも制約の付け方に一癖ある代物。そんなScrollViewと、AutoLayoutへの理解に横着したものが愛用するStackViewを組み合わせるのは、おそらく結構な冒険。。
やってみたところ案の定制約の付け方でつまづいたところがあったので、この度メモ書きとして記事に残しておこうと思いました。
「縦スクロールするStackView」を作るまでの手順に沿って、説明していきます。

1.ViewControllerにScrollViewを配置する

ViewController内にScrollViewを配置しましょう。
で、ScrollViewに親ビューに対して上下左右スペース0の制約をつけます。
これで画面いっぱいにScrollViewが広がることになります。

スクロールさせたいコンテンツはこのScrollView内に配置していけばOkてことっすな。

2.ScrollViewにStackViewを配置する

ScrollView内にStackViewを配置しましょう。
で、StackViewに親ビューに対して上下左右スペース0の制約をつけます。
これでScrollViewいっぱいにStackViewが広がること... にはなりません!

【ポイント】
ここで意識しておきたいのが、ここでつけた制約は親ビューであるScrollViewに対してではなく ScrollViewのContentSizeに対してつけられた ということです。(表現として完全に適切ではなさそうですが。。)

(ContentSizeについてはこちらの記事に詳しく書いてあったのでご参照ください。)

StackView に上下左右スペース0つけたとして、StackViewのサイズと親ビューScrollViewのサイズとが同じになるというわけではなく、StackViewのサイズと ScrollView.contentSizeとが 同じ大きさとなります。ScrollView.contentSizeの大きさは子ビューの大きさが決まらないと決まりません。

ので、上下左右スペース0の制約をつければ親ビューの画面いっぱいに広がる!という考え方は、親ビューがUIScrollViewの場合通用しません!><
必ず子ビュー(ここでいうStackView)のサイズを決めなければ全体のサイズが決まらず、制約の付け方が不十分であるという旨の赤い警告が表示されるはずです。

めっちゃややこしいですが、一応これでStackViewのサイズに合わせてScrollView.contentSizeの大きさも変わるようにはなりました。
つまり、StackViewの大きさがScrollView自体の大きさを超えている場合、StackViewの大きさに合わせてScrollView.contentSizeの大きさも広がり、ちゃんとスクロールできるようになったよ。ということですわ。

では、次のステップでStackViewの大きさがちゃんと決まるようにしていきましょう。

3.StackViewにView(Labelなんか)を配置する

StackView内に、レイアウトしたいLabelなんかをいろいろ配置しましょう。
で、StackViewのAxis(今回は縦スクロールなのでvertical)やAlignmentやDistributionなんかの設定をいろいろ決めてあげます。
SackViewについてはこちらに詳しく書いてあったのでご参照ください。
これでStackViewいっぱいにいい感じにViewたちが配置されます。

中身のViewたちの大きさが決定すれば、それによってStackViewの大きさも決定します。
UILabelなんかは特別制約を設定しなくても、フォントや行数によって大きさが決定するViewなので、StackViewにそのまま突っ込んでやるだけで、前のステップで出ていただろう制約に関する警告は消えてくれるはずです。
めでたしめでたし。

4. StackViewの幅調整

ここまででで、

  • StackViewの中身が大きくなったら、それに伴ってStackViewも広がってくれるようになりました。
  • そしてさらにそれに伴ってScrollView.contentSizeも広がってくれるので、StackViewの大きさが画面サイズからはみ出すくらいになってもちゃんとスクロールしてくれるようになりました。
  • いい感じ。

しかしまだ不十分な部分があります。
(ここが、はじめに言ったつまづいた部分でもあります。)

今回作るスクロールビューは縦スクロールの設定なのに、ここまでのやり方だとStackViewが横に大きくなってしまった場合におかしくなります。横幅はきっちり画面幅に合わせておきたい。。
ステップ2でStackViewに上下左右スペース0の制約をつけたのだから、横幅は親ビューであるScrollViewと同じになってるでしょ?横には広がらないよ?
と、思うかもしれません。いやいや、思い出してください。

ステップ2で

StackViewのサイズと親ビューScrollViewのサイズとが同じになるというわけではなく、StackViewのサイズと ScrollView.contentSizeとが 同じ大きさとなります。

と言ってたところですね。
StackViewの横幅はScrollViewと同じにはなっていません。
StackViewに上下左右スペース0の制約をつけることによって実現するのは、StackViewの大きさ(StackViewの中身によって広がった大きさ)に合わせてScrollView.contentSizeが決まるということだけです。

ので、StackViewの横幅がScrollView自体の横幅より大きくなってしまわないように、StackViewに対して width = 親ビューのwidthの制約をつけてあげる必要があります。
ここまでやってあげれば完璧です。b

だんだん記事が雑になってきてる気がしますね。。
わかりにくかったらすみません。もしお役に立てていたら何かしら反応いただけると嬉しく思います。

39
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
27