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やスクロールをしたとき、更にはそのままデバイスを回転させた時などの挙動
あたりを調べれば、大方スッキリするとおもう。