UIScrollView: paging horizontally, scrolling vertically?

后端 未结 20 1253
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 09:09

How can I force a UIScrollView in which paging and scrolling are on to only move vertically or horizontally at a given moment?

My understanding is that

相关标签:
20条回答
  • 2020-11-27 09:47

    I used following method to solve this problem, hope it helps you.

    First define following variables in your controllers header file.

    CGPoint startPos;
    int     scrollDirection;
    

    startPos will keep the contentOffset value when your delegate receives scrollViewWillBeginDragging message. So in this method we do this;

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        startPos = scrollView.contentOffset;
        scrollDirection=0;
    }
    

    then we use these values to determine users intended scroll direction in scrollViewDidScroll message.

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    
       if (scrollDirection==0){//we need to determine direction
           //use the difference between positions to determine the direction.
           if (abs(startPos.x-scrollView.contentOffset.x)<abs(startPos.y-scrollView.contentOffset.y)){          
              NSLog(@"Vertical Scrolling");
              scrollDirection=1;
           } else {
              NSLog(@"Horitonzal Scrolling");
              scrollDirection=2;
           }
        }
    //Update scroll position of the scrollview according to detected direction.     
        if (scrollDirection==1) {
           [scrollView setContentOffset:CGPointMake(startPos.x,scrollView.contentOffset.y) animated:NO];
        } else if (scrollDirection==2){
           [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x,startPos.y) animated:NO];
        }
     }
    

    finally we have to stop all update operations when user end dragging;

     - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
        if (decelerate) {
           scrollDirection=3;
        }
     }
    
    0 讨论(0)
  • 2020-11-27 09:48

    I managed to solve this by implementing scrollViewDidBeginDragging(_:) and looking at the velocity on the underlying UIPanGestureRecognizer.

    NB: With this solution, every pan that would have been diagonal will be ignored by the scrollView.

    override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        super.scrollViewWillBeginDragging(scrollView)
        let velocity = scrollView.panGestureRecognizer.velocity(in: scrollView)
        if velocity.x != 0 && velocity.y != 0 {
            scrollView.panGestureRecognizer.isEnabled = false
            scrollView.panGestureRecognizer.isEnabled = true
        }
    }
    
    0 讨论(0)
  • 2020-11-27 09:49

    Need to reset _isHorizontalScroll to NO in touchesEnded and touchesCancelled.

    0 讨论(0)
  • 2020-11-27 09:49

    If you are having a big scrollview... and you want to restrict the diagonal scrolling http://chandanshetty01.blogspot.in/2012/07/restricting-diagonal-scrolling-in.html

    0 讨论(0)
  • 2020-11-27 09:49

    For those looking in Swift at @AndreyTarantsov second solution its like this in code:

        var positionScroll:CGFloat = 0
    
        func scrollViewWillBeginDragging(scrollView: UIScrollView) {
            positionScroll = self.theScroll.contentOffset.x
        }
    
        func scrollViewDidScroll(scrollView: UIScrollView) {
            if self.theScroll.contentOffset.x > self.positionScroll || self.theScroll.contentOffset.x < self.positionScroll{
                 self.theScroll.pagingEnabled = true
            }else{
                self.theScroll.pagingEnabled = false
            }
        }
    

    what we are doing here is to keep the current position just before scrollview gets dragged and then check if either x has increased or decreased compared to the current position of x. If yes, then set the pagingEnabled to true, if no (y has increased/decreased) then set to pagingEnabled to false

    Hope that is useful to new comers!

    0 讨论(0)
  • 2020-11-27 09:50

    Thanks Tonetel. I slightly modified your approach, but it was exactly what I needed to prevent horizontal scrolling.

    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, 1);
    
    0 讨论(0)
提交回复
热议问题