1

I am trying to get a UICollectionView to scroll either completely vertically or completely horizontally, depending on the direction of the swipe/pan.

There should be no diagonal scrolling.

If a user swipes in a diagonal direction, it should choose the stronger direction, either vertical or horizontal, and then scroll in only that direction.

The other answers on the web are related to using a CollectionViewFlowLayout, which allows a single direction. But, I had to subclass the UICollectionViewLayout in order to allow both horizontal and vertical scrolling.

Now, I want to disable the diagonal scrolling, but keep the ability to horizontally/vertically scroll.

I have already used the collectionView.isDirectionLockEnabled, but according to apple Docs:

If this property is true and the user begins dragging in one general direction (horizontally or vertically), the scroll view disables scrolling in the other direction. If the drag direction is diagonal, then scrolling will not be locked and the user can drag in any direction until the drag completes.

It still allows diagonal scrolling, hence not very helpful to my desired goal.

I am looking for some sort of override point where I could catch the direction of the drag/scroll, and then only allow a certain direction to be scrolled.

EDIT: Here is my relevant code. This code has made it harder to scroll diagonally, but on occasion, I can still get it to scroll diagonally:

var initialContentOffset: CGPoint = CGPoint.zero

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    initialContentOffset = scrollView.contentOffset
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.isDragging {
        let velocity = scrollView.panGestureRecognizer.velocity(in: scrollView)

        if abs(velocity.y) > abs(velocity.x) {
            scrollView.contentOffset = CGPoint(x: initialContentOffset.x, y: scrollView.contentOffset.y)
        } else if abs(velocity.x) > abs(velocity.y) {
            scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: initialContentOffset.y)
        }
    }
}
Daniel Jones
  • 1,032
  • 10
  • 18
  • this might give you an answer if not the duplicate: http://stackoverflow.com/questions/18464153/how-can-i-change-the-scroll-direction-in-uicollectionview and you have a tutorial here if you need more details : http://www.brightec.co.uk/ideas/uicollectionview-using-horizontal-and-vertical-scrolling-sticky-rows-and-columns together with sample code provided: https://github.com/brightec/CustomCollectionViewLayout –  Feb 28 '17 at 06:36
  • I have looked at all of those links. I have already figured out how to allow both horizontal and vertical scrolling, but with that ability, it also scrolls in a diagonal fashion if a gesture is in a diagonal direction. I want to exclude diagonal scrolling. I've scoured the web for hours looking for a solution, but none have worked properly. – Daniel Jones Feb 28 '17 at 06:46
  • 1
    I retracted the flag. If those tutorials and links did'nt help you, your option is to just simply handle the scrolling "direction locks" inside the scrollView delegate methods. This might help: http://stackoverflow.com/questions/14042203/detect-direction-of-uiscrollview-scroll-in-scrollviewwillbegindragging or https://www.google.se/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=uiscrollview+detect+direction+of+scroll&* –  Feb 28 '17 at 06:54
  • I actually already know how to get check the velocity/direction of the scroll by using the delegate methods to access the collection view's scrollview, then I can use scrollview.pangesture.velocityIn(scrollView) to get the direction. My problem becomes, even by knowing the direction, how can I control the collection view to only scroll vertically/horizontally. I have attempted to use scroll view delegate methods (UICollectionView is a subclass of UIScrollView), but I have yet to get good functionality. Setting the content offset is producing weird effects. – Daniel Jones Feb 28 '17 at 07:03
  • then you can just set the contentOffset depending on which way it wants to scroll and is currently scrolling (x or y), and you are good to go? –  Feb 28 '17 at 07:04
  • But, in what method do I set the new content Offset? If I use scrollViewDidScroll, then the collectionView has already scroll, and the effects are weird. – Daniel Jones Feb 28 '17 at 07:15
  • Setting content Offset in `scrollViewDidScroll` with an animation will solve the issue. Could you please include code that you're tried out? – arunjos007 Feb 28 '17 at 08:44

1 Answers1

1

You should do a combination of checking against multiple delegates of the scrollView. Check direction of scroll in UIScrollView

1: you need to keep a Boolean property isScrolling to know if the scrollView is scrolling or if it has stopped, and probably a property to keep a reference to which direction the user is currently scrolling if (isScrolling == YES)

2: Now in this method:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

We need to check what direction the user will scroll and at the same time , you can do a check against the first flag isScrolling:

  • if the scrollView has stopped scrolling, you allow the scrolling to begin and set the isScrolling flag to YES and only allow the scrolling in one direction.
  • if the scrollView has not stopped scrolling, you simply set the scrollView.contentOffset x or y, depending on which direction you want to allow the scrollView to keep scrolling.
Community
  • 1
  • 1
  • I tried implementing your suggestions, but I must be doing something wrong because I just can't get the desired effect. I'm not totally sure where to put the isScrolling part. If you wouldn't mind, could you post the relevant code. I really appreciate your help. – Daniel Jones Feb 28 '17 at 22:45
  • 1
    @DanielJones I see, I am sorry atm I have my hands full with a project, but, I did look up a simple tutorial exactly where you should put it, check this out: http://bogdanconstantinescu.com/blog/proper-direction-lock-for-uiscrollview.html He created exactly what you need. It is in objective-c , but it is very straightforward and you should be able to handle it. If you run into problems let me know il see what I can do for you. –  Feb 28 '17 at 22:59
  • I already attempted to follow that blog. It still did not fix the problem. https://github.com/bogdanconstantinescu/ScrollViewDirection/issues/1 – Daniel Jones Mar 01 '17 at 06:40
  • 1
    @DanielJones I will look at this tonight when I am home if you havnt solved it by then I will update with code. I am coding in objective-c but I will give you the methods and calculations needed. –  Mar 01 '17 at 06:44
  • @DanielJones Sorry for forgetting about this thread. I think I have fixed the issues with the demo project on github. If you add an email here I can send it to you. –  Mar 05 '17 at 19:04
  • 1
    @DanielJones I will email you it now, you can delete your email comment, I have commented the code for you so you understand what I have done. It is 99.9% perfect, however, you can figure out that 0.1% yourself I have commented for you :) –  Mar 06 '17 at 18:11