UIScrollViewのcontentOffsetはスクロール位置を測るためによく使われるけど、contentSizeに対して値が変だなと思った部分があったのでまとめ。
そもそもcontentOffsetとは
UIScrollViewのスクロール位置が初期状態(= contentOffset = {0, 0})の状態からx, y方向にどれだけスクロールしたかを表す。y方向に+100pxスクロールしたらcontentOffsetは{0,100}になる。当たり前。
contentSizeとcontentOffset
contentSizeはUIScrollViewのframe内の総サイズを表す。たとえば、200x200の画像を100x100のフレームでscale:1.0で表示させようとした場合のcontentSizeは{200,200}。これも当然。
BouncingとcontentOffset
なのだけど、UIScrollViewにはbouncingオプションがあって、x,y方向へのぼよよ~ん処理が可能。この場合contentOffsetはどうなるかというと、例えばoffsetが{0,0}の状態で下に引っ張ってbouncingさせると{0,-xx}という値になる。maxがどこまでなのかは不明。とりあえず、contentOffsetはマイナスの値も取る。
逆に、端までスクロールしてそのままに引っ張ったときcontentOffsetはどうなるかというと、contentSizeの値は超えない。これがちょっと不思議だったけどよく考えたら納得。
なぜかというと、contentOffsetはどれだけスクロールしたかというよりはむしろ名前の通り、いま表示している領域の基準点(左上とか)がoriginからどれだけ離れているかを表しているから。なので、先の例だと画像を左上から右下までスクロールした場合のcontentOffsetの値は{200,200}ではなく{100,100}。
なので、x,y方向にどれだけの割合スクロールしたかを求めたい場合は、contentOffsetの値にbound.sizeの値を足してやる必要がある。なので、以下の様な式で計算するといまscrollViewがどれくらいスクロールしているのかがわかる。
スクロールした割合(%) = contentOffset + bound.size / contentSize
contentInset
しかし、これにcontentInsetが設定されている場合、それも加味しなければならないので注意が必要。
スクロールした割合(%) = contentOffset + bound.size - contentInset / contentSize
かな? 自信ないけど