More than 1 year has passed since last update.

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

かな? 自信ないけど