How to get UIScrollView vertical direction in Swif

2020-01-28 02:36发布

How can I get the scroll/swipe direction for up/down in a VC?

I want to add a UIScrollView or something else in my VC that can see if the user swipes/scrolls up or down and then hide/show a UIView depending if it was an up/down gesture.

11条回答
▲ chillily
2楼-- · 2020-01-28 03:05

I've found that this is the simplest and most flexible option (it works for UICollectionView and UITableView as well).

override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    switch velocity {
    case _ where velocity.y < 0:
        // swipes from top to bottom of screen -> down
        trackingDirection = .down
    case _ where velocity.y > 0:
        // swipes from bottom to top of screen -> up
        trackingDirection = .up
    default: trackingDirection = .none
    }
}

Where this doesn't work though, is if there is 0 velocity - in which case you'll have no choice but to use the accepted answer's stored property solution.

查看更多
Deceive 欺骗
3楼-- · 2020-01-28 03:08

For swift4

public func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if(scrollView.panGestureRecognizer.translation(in: scrollView.superview).y > 0) {
            print("up")
        }
        else {
            print("down")
        }
    }
查看更多
萌系小妹纸
4楼-- · 2020-01-28 03:08

Simply add this method to your view controller:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (scrollView.contentOffset.y < 0) {
        // Move UP - Show Navigation Bar
        self.navigationController?.setNavigationBarHidden(false, animated: true)
    } else if (scrollView.contentOffset.y > 0) {
        // Move DOWN - Hide Navigation Bar
        self.navigationController?.setNavigationBarHidden(true, animated: true)
    }
}
查看更多
贼婆χ
5楼-- · 2020-01-28 03:11

Victor's answer is great, but it's quite expensive, as you're always comparing and storing values. If your goal is to identify the scrolling direction instantly without expensive calculation, then try this using Swift:

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)
    if translation.y > 0 {
        // swipes from top to bottom of screen -> down
    } else {
        // swipes from bottom to top of screen -> up
    }
}

And there you go. Again, if you need to track constantly, use Victors answer, otherwise I prefer this solution.

查看更多
6楼-- · 2020-01-28 03:13

If you use an UIScrollView then you can take benefit from the scrollViewDidScroll: function. You need to save the last position (the contentOffset) it have and the update it like in the following way:

// variable to save the last position visited, default to zero
private var lastContentOffset: CGFloat = 0

func scrollViewDidScroll(scrollView: UIScrollView!) {
    if (self.lastContentOffset > scrollView.contentOffset.y) {
        // move up
    }
    else if (self.lastContentOffset < scrollView.contentOffset.y) { 
       // move down
    }

    // update the new position acquired
    self.lastContentOffset = scrollView.contentOffset.y
}

There are other ways of do it of course this is one to them.

I hope this help you.

查看更多
劫难
7楼-- · 2020-01-28 03:13

I have tried every single response in this thread but none of them could provide a proper solution for a tableView with bounce enabled. So I just used parts of solutions along with some all-time classic boolean flag solution.

1) So, first of all you could use an enum for the scrollDirection:

enum ScrollDirection {
    case up, down
}

2) Set 3 new private vars to help us store lastOffset, scrollDirection and a flag to enable/disable the scroll direction calculation (helps us ignore the bounce effect of tableView) which you will use later:

private var shouldCalculateScrollDirection = false
private var lastContentOffset: CGFloat = 0
private var scrollDirection: ScrollDirection = .up

3) In the scrollViewDidScroll add the following:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // The current offset
    let offset = scrollView.contentOffset.y

    // Determine the scolling direction
    if lastContentOffset > offset && shouldCalculateScrollDirection {
        scrollDirection = .down
    }
    else if lastContentOffset < offset && shouldCalculateScrollDirection {
        scrollDirection = .up
    }

    // This needs to be in the last line
    lastContentOffset = offset
}

4) If you have not implemented scrollViewDidEndDragging implement it and add these lines of code inside it:

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    guard !decelerate else { return }
    shouldCalculateScrollDirection = false
}

5) If you have not implemented scrollViewWillBeginDecelerating implement it and add this line of code inside it:

func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
    shouldCalculateScrollDirection = false
}

6) Finally, If you have not implemented scrollViewWillBeginDragging implement it and add this line of code inside it:

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {    
    shouldCalculateScrollDirection = true
}

And if you followed all the steps above you are good to go!

You could go to wherever you want to use the direction and simply write:

switch scrollDirection {
case .up:
    // Do something for scollDirection up
case .down:
    // Do something for scollDirection down
}
查看更多
登录 后发表回答