UIScrollViewを一方向だけにしかスクロールを許さない方法

縦だけとか横だけのサンプルは良く見かけるのですが、例えば上スクロールだけを許して下にはスクロールさせない方法が見つからなかったので書いておきます。
(こんな制御に需要があるとはあまり思えませんが。。)

ポイント1 スクロール方向の判定

UIScrollViewDelegateのscrollViewWillBeginDragging、scrollViewDidScrollでスクロールの前回座標を保存し、
scrollViewDidScrollでスクロールされた後の座標と比較すればOK

ポイント2 スクロールのキャンセル

スクロールの方向を求め、許可する方向以外だった時はスクロールの位置をスクロールの開始座標に戻します。
また、座標を戻したとしても慣性スクロールが発生しますのでscrollViewWillBeginDeceleratingで慣性スクロールをキャンセルします。(以前の記事参照

実装は下記みたいな感じです

UIScrollViewDelegateを宣言に追加しておいて下さいね

//インスタンス変数としてどこかに宣言してください
CGPoint _scrollPrevPoint;  //スクロールの開始位置
BOOL _cancelDecelerating;  //慣性スクロールをキャンセルするフラグ    
int _scrolling_direction;  //0:未確定 1:上(offset.yが小さくなる) 2:下(offset.yが大きくなる)


#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{

    _scrolling_direction = 0;
    _cancelDecelerating = false;
    _scrollPrevPoint = [scrollView contentOffset];
}


-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGPoint currentPoint = [scrollView contentOffset];
   
    if (CGPointEqualToPoint(_scrollPrevPoint, currentPoint)){
        return;
    }
    else {
     //スクロール方向の判定
        _scrolling_direction = (_scrollPrevPoint.y < currentPoint.y) ? 2 : 1;
    }
   
    //下スクロールのキャンセル
    if (_scrolling_direction == 2)
    {    
        currentPoint.y = _scrollPrevPoint.y;
        [scrollView setContentOffset:currentPoint];
        _cancelDecelerating = true; //慣性スクロールを止めるためのフラグをセット
    }
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    //慣性スクロールを止める
    if (_cancelDecelerating){
        [scrollView setContentOffset:scrollView.contentOffset animated:NO];
    }
}

上記のような実装を行ったインスタンスをUIScrollViewのdelegateに指定してあげればOK

以上

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です