UIScrollViewを使うときに注意することメモ(AutoLayout関係)

#はじめに
UIScrollViewを使うと急なButtonの追加やレイアウトの変更が起こったときに、画面からはみ出てしまってもスクロールすれば表示されるからひとまずいいか、となって安心できるのでUIScrollViewを下地に貼るのがおすすめらしいです。
実際サンプルアプリの改修をしているときにボタンが増えてレイアウトに困ったときに、ScrollView貼っとけばよかったなと思いました。

https://github.com/eueuG/UIScrollViewSample

が、下地に貼る作業がちょっと難しいので手順のメモを残しておきます。

今回はUISclollViewでできるシンプルなスクロールできるページの実装とStackViewを用いた実践的（？）（というか自分で助かった実装）をやってみます。


###目次
-[実装1.シンプルなスクロールページ](#実装1.シンプルなスクロールページ)
-[実装2.シンプルなスクロールページをStackViewを使って実装](#実装2.上と同じものをStackViewを使って作る。)
-[実装3.便利だなと思ったUIScrollViewとStackViewの合わせ技](#実装3.便利だなと思ったUIScrollViewとStackViewの合わせ技)

#実装1.シンプルなスクロールページ
今回目指すのはこんな感じのviewです。

![Scroll.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/bd73e7a6-827a-4fd5-e5b1-9e6ebcbf777f.gif)


やっていきます。
##Step1.UIScrollViewをviewの全面に貼る

右上の+ボタンからUIScrollViewをドラッグアンドドロップしてきたら、親viewに対して画像のように制約をつけていきます。
これで、UIScrollViewが全面に貼れたことになります。エラーが出てきますが気にしなくて大丈夫です。

![スクリーンショット 2021-05-09 13.24.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/c506a117-ce1e-261a-323b-a42e5cc5735b.png)

##Step2.UIScrollView内にViewを貼り付ける
先ほどと同じようにしてViewをドラッグアンドドロップして、制約をつけていきます。名前はContentsViewをしておいてください。
ContentsViewから同じ階層にあるContentLayoutGuideに向かって`controllキー`を押したままにょーんとドラッグアンドドロップしたらメニューが表示されます。
その中の４つの項目を`commandキー`を押しながら選択します。画像のようになっていればOKです。
![スクリーンショット 2021-05-09 13.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/132d8883-4b98-db69-8b2e-a231acb30445.png)

:warning: **このとき今つけた制約一つ一つについてConstantの値が0になっていることを確認してください。** 
ついでに下のMultiplierの値も１になっていることを確認しましょう。（左側のメニューからConstraintsを選択して個々の項目についてAttributeInspecterで確認します。）
正直ここが一番大切なのではという気もします。制約を貼り付けたはいいがエラーが出ていたり、一見予想したレイアウトになってなくて心が折られることが多いですが、だいたいconstantかMultiplierの値が適当なものになっているのが原因だと思います。
詳しく知りたい方は下のリンクのApple公式ドキュメントが参考になると思います。
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/AnatomyofaConstraint.html#//apple_ref/doc/uid/TP40010853-CH9-SW1

![スクリーンショット 2021-05-09 13.36.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/53efad09-9916-3582-f85e-f6bd3e469dcd.png)

そして同じようにしてContentsViewとFrameLayoutGuideに対しても制約をつけていきます。
チェックするのは **Equal Heights** の項目です。（縦スクロールさせたい時はEqual Widths）
![スクリーンショット 2021-05-09 13.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/3ccf6184-26a8-def3-e676-a88c660e3083.png)

##Step3.ContentsView内にPage1になるviewを貼り付ける
先ほどと同じようにしてViewをドラッグアンドドロップします。名前はPage1にしておきます。Page1とContentsViewの間につける制約は **TopとBottom、Leading** です。画像のようにチェックします。

![スクリーンショット 2021-05-09 14.01.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/3e1ecda7-8b1f-8c40-312a-3453eba196d0.png)

また、Page1とFrameLayoutGuideの間には **EqualWidths** をつけておきます。

##Step4.ContentsView内にPage2になるViewを貼り付ける。
これも先ほどとほぼ同様ですが、Page2とContentsViewの間の制約は **TopとBotttomとTrailing** です。
![スクリーンショット 2021-05-09 14.08.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/1dc45530-788e-ed44-7f9f-00e58a8e021c.png)

そしてPage2とFrameLayoutGuideの間には **EqualWidths** の制約をつけます。

##Step5.Page1とPage2を水平方向に並べる。
Page1とPage2の間に制約をつけます。`controllキー`を押しながらドラッグアンドドロップして、 **Horizontal Spacing** にチェックをつけます。

![スクリーンショット 2021-05-09 14.14.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/b4041292-3cee-3f13-ddce-fb564148c0f3.png)

このとき今つけた制約を左のメニューから選択して（constantとMultiplierの値を確認するときみたいに）
右側のFirst ItemとSecond Itemの値を確認してください。画像のように **Page１.TrailingとPage2.Leading** がつながっていれば大丈夫です。

![スクリーンショット 2021-05-09 14.26.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/1c2b3640-1610-7e2d-c494-0f50da6b32da.png)


##Step6.完成！

最後につけた制約のconstantの値とMultiplierの値を見直してみてください。
スクロールできるはずです。
あとはPageの背景色を変えてみたりしてわかりやすくするのもいいかもしれません。




#実装2.上と同じものをStackViewを使って作る。

##Step1.UIScrollViewをviewの全面に貼る
ここは先ほどと全く同じです。

##Step2.UIScrollView内にHorizontalStackViewを貼り付ける

ここも先ほどのViewを貼り付ける作業と全く同じです。StackViewの名前をConentsViewと変更しておきます。

StackView内にViewを貼り付ける際にStackViewの利点が明らかになります。

##Step3.ContentsView内にPage1になるviewを貼り付ける
やることは一緒なのでviewをContentsViewまでドラッグ&ドロップします。名前をPage1としておきます。
そしてPage1とFrameLayoutGuideとの間に制約をつけます。
チェックを入れる項目はEqualWidthsとEqualHeightsです。画像のようになっていれば大丈夫です。

ここでConstantとMultiplierの値を確認しておきましょう。

![スクリーンショット 2021-05-09 16.13.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/eb30994a-ed2f-edae-13fd-16a75a7fd113.png)

##Step4.ContentsView内にPage2になるViewを貼り付ける。
ここまでと同じようにviewをドラッグアンドドロップします。
そしてPage1でやったのと同じようにPage2もFrameLayoutGuideとの間に **EqualWidths、EqualHeights** の項目にチェックを入れます。

最後にConstantとMultiplierの値を確認して。。。


##Step5.完成！

StackViewを使わない方より少ない手順で出来上がりましたね。

実際使用したConstraintsもこれくらい少なく済みました。
左が実装２のStackViewを用いたもの、右が実装１のものです。

![スクリーンショット 2021-05-09 16.30.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/2b78e094-1029-30f9-40f6-60096c331209.png)

とこんな感じでUIScrollViewの実装をします。

#実装3.便利だなと思ったUIScrollViewとStackViewの合わせ技

こんな感じにいくつかScrollViewの使い方をまとめたサンプルアプリを作っている途中、ボタンを追加するときにいちいち今までの制約を外して動かして制約つけて。。。とやるのは手間がかかるので、ボタンを追加したときに自動でいい感じに並んでくれたらいいのになということを考えました。

![スクリーンショット 2021-05-09 17.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/633ad18d-4631-9612-1c55-2429268534e4.png)

というわけでボタンを並べたときにViewからはみ出てしまってもスクロールできるようにしておく方法を実装していきます。

##Step1.UIScrollViewをViewの全面に貼る

省略

##Step2.UIScrollView内にViewを貼り付ける

省略

ContentsViewという名前にしておきます。同じです。

##Step3.ContentsView内にVerticalStackViewを貼る。

StackViewにつける制約はHorizontallyinContainerと、ContantsViewに対してTopとBottomをつけます。画像のようになっていれば大丈夫です。

![スクリーンショット 2021-05-09 18.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/7253ccd2-d83c-57c2-2047-983c1987c4fe.png)

##Step4.StackView内にボタンを置きまくる。

6個くらいボタンを配置します。ボタン同士の間隔はAttributeInspectorのSpacingという項目で変更します。150くらいにしておきます。

最後に一番上のボタンとNavigation Barの間が狭いので間隔を開けます。
StackViewのTopのConstrainのconstantを100とします。同様にBottomのConstantも100にしておきます。

画像を参考にしてみてください。

![スクリーンショット 2021-05-09 18.16.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/3289a0bd-71e6-acc6-7b15-1bbd8e178f1f.png)

##Step5.完成！
![Vertical.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1222455/06ea53f3-a268-c2e1-bf2b-e25a48d9ec35.gif)
こういう風にしておけばボタンを追加するときにStackViewに入れるだけで、きちんとUIに表示されるようになるので楽チンです。もっと細かいレイアウトを要求される場合はここまで単純ではないかもしれませんが、うまくScrollViewやStackViewを使うことで改修が楽になると考えられますね。


###最後に
間違っている点や、ここはこうした方が良いなどありましたら教えてくださるとありがたいです！