定食屋おろポン

おろしポン酢と青ネギはかけ放題です

UIScrollViewについて頭をスッキリさせてみよう。-contentSize編-

UIScrollViewのcontentSizeが理解できずに夜中までXcodeをいじっていた。

なにが分からないのか。

大きな画像をScrollViewにaddSubviewしてスクロールさせるやりかたは分かる。
ピンチで画像を拡大できるようにするやり方もわかる。
しかし、サブビューに入れたコンテンツの大きさが変わったり、キーボードが出たりしたときに、表示はすぐに崩れてしまう。そういったとき、「どのタイミングで」「どの値に」「何の値を入れ」ることで、適切にレイアウトされるのかがわからない。
試行錯誤も大事だが、毎回試行錯誤していては時間ばかりが過ぎてしまう。頭をクリアにしたかったんだ。
そこでまずはcontentSizeを見てみた。

簡単に検証

  • UIScrollView* scrollView; (bounds.size:320*480)
  • UILabel* label; (bounds.size:320*800)

この二つを用意した。もちろんLabelはScrollViewのサブビューだ。

1.scrollView.contentSize = label.bounds.size;

ScrollViewのcontentSizeを、labelの大きさと同じにした。つまり320*800
緑がlabel.size、赤の枠がscrollView.contentSize、青の枠がデバイスの可視範囲をそれぞれ表す。

これは縦のみスクロール可能な、至って普通のサンプルだ。
scrollView.contentSize: 320*800
label.bounds.size: 320*800
デバイスの可視範囲: 320*460

2. そのままデバイスを横に傾けLandscapeにする

scrollView.contentSizeは320*800のままだが、labelはオートリサイズするためサイズが変わる。

これも縦にのみスクロール可能。だが、一番下までスクロールすると300ポイント弱の余白が生じる。
青枠のデバイス可視範囲に含まれているけれど真っ白のゾーンがそれだ。
scrollView.contentSize: 320*800
label.bounds.size: 480*541
デバイスの可視範囲: 480*300
デバイスでどう見えるかも併せて撮ってみた。一番下までスクロールした状態。大きな余白が生じている。

3. scrollView.contentSizeを20*800、label.sizeを500*800にしてみる。

デバイスは縦にする。

するとこれも、縦にのみスクロール可能となる。
scrollView.contentSize: 20*800
label.bounds.size: 500*800
デバイスの可視範囲: 320*460
青枠で示されたデバイスの表示幅より右のlabelは、スクロールできないため、見ることができない。
なお、赤枠はとても狭いが、それ以外のところをスワイプしても画面はスクロールできる。

考察

至って単純な結果が見えてくる。
scrollView.contentSizeの幅が、scrollView.boundsの幅より大きい場合には横方向にスクロール可能。
高さも同様。
実際にスクロールして見たいサブビューの大きさがなんであれ、contentSizeの端までスクロールできる。
なーんだ。それだけか。
まあ、「それだけ」ではあってもUIScrollViewが何者なのかが結構見えてきた。
あとは

  • scrollViewの中にscrollViewがある場合にはどうなるか?
  • contentInset, contentOffset, scrollIndicatorInsetsに値を与えた時の挙動
  • UIScrollViewを継承した子供たちの挙動
  • Zoomやスクロールをしたとき、更にはそのままデバイスを回転させた時などの挙動

あたりを調べれば、大方スッキリするとおもう。