Подтвердить что ты не робот

Как получить вертикальное направление UIScrollView в Swift?

Как я могу получить направление прокрутки/прокрутки вверх/вниз в VC?

Я хочу добавить UIScrollView или что-то еще в своем VC, который может видеть, что пользователь выполняет прокрутку или прокрутку вверх или вниз, а затем скрыть/показать UIView в зависимости от того, был ли это жест вверх/вниз.

4b9b3361

Ответ 1

Если вы используете UIScrollView, вы можете воспользоваться функцией scrollViewDidScroll:. Вам нужно сохранить последнюю позицию (contentOffset) и обновить ее следующим образом:

// 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
}

Есть и другие способы сделать это, конечно, это один из них.

Надеюсь, это поможет вам.

Ответ 2

Ответ Виктора хорош, но он довольно дорогой, так как вы всегда сравниваете и храните значения. Если ваша цель состоит в том, чтобы определить направление прокрутки мгновенно без дорогостоящего расчета, попробуйте это с помощью 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
    }
}

И вот, пожалуйста. Опять же, если вам нужно постоянно отслеживать, используйте ответ Victors, в противном случае я предпочитаю это решение. 😊

Ответ 3

Я использовал ответ Виктора с небольшим улучшением при прокрутке за конец или начало прокрутки, а затем при возврате эффекта возврата. Я добавил ограничение путем вычисления (scrollView.contentSize.height - scrollView.frame.height), а затем ограничение диапазона scrollView.contentOffset.y будет больше 0 или меньше (scrollView.contentSize.height - scrollView.frame.height), при отскакивании назад никаких изменений не происходит.

 //code

    if(self.lastContentOffset > scrollView.contentOffset.y) &&
    self.lastContentOffset < (scrollView.contentSize.height - scrollView.frame.height) {
        // move up
        buttonAdd.hidden = false
    }
    else if (self.lastContentOffset < scrollView.contentOffset.y 
 && scrollView.contentOffset.y > 0) {
    // move down
        buttonAdd.hidden = true
    }

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

Ответ 4

Swift 2-4 с помощью UISwipeGestureRecognizer

Другой вариант - использовать UISwipeGestureRecognizer, который распознает UISwipeGestureRecognizer в запрошенном направлении (это будет работать во всех представлениях, а не только в UIScrollView

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let upGs = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.handleSwipes(sender:)))
        let downGs = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.handleSwipes(sender:)))

        upGs.direction = .up
        downGs.direction = .down

        self.view.addGestureRecognizer(upGs)
        self.view.addGestureRecognizer(downGs)
    }

    @objc func handleSwipes(sender:UISwipeGestureRecognizer) {

        if (sender.direction == .up) {
            print("Up")
        }

        if (sender.direction == .down) {
            print("Down")
        }
    }
}

Ответ 5

Для Swift Я думаю, что самый простой и мощный способ сделать, как показано ниже. Он позволяет отслеживать изменение направления и реагировать только один раз при его изменении. Кроме того, вы всегда можете получить доступ к прокручиваемому свойству .lastDirection, если вам нужно проконсультироваться с этим кодом на любом другом этапе.

enum WMScrollDirection {
    case Up, Down, None
}

class WMScrollView: UIScrollView {
    var lastDirection: WMScrollDirection = .None {
        didSet {
            if oldValue != lastDirection {
                // direction has changed, call your func here
            }
        }
    }

    override var contentOffset: CGPoint {
        willSet {
            if contentOffset.y > newValue.y {
                lastDirection = .Down
            }
            else {
                lastDirection = .Up
            }
        }
    }
}

Вышеупомянутое предполагает, что вы отслеживаете только прокрутку вверх/вниз. Он настраивается через перечисление. Вы можете добавить/изменить на .left и .right для отслеживания любого направления.

Я надеюсь, что это поможет кому-то.

Приветствия

Ответ 6

вы можете сделать что-то вроде этого:

fileprivate var lastContentOffset: CGPoint = .zero

func checkScrollDirection(_ scrollView: UIScrollView) -> UIScrollViewDirection {
    return lastContentOffset.y > scrollView.contentOffset.y ? .up : .down
}

и с scrollViewDelegate:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    switch checkScrollDirection(scrollView) {
    case .up:
        // move up
    case .down:
        // move down
    default:
        break
    }

    lastContentOffset = scrollView.contentOffset
}

Ответ 7

Я обнаружил, что это самый простой и гибкий вариант (он работает и для UICollectionView и UITableView).

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
    }
}

Если это не работает, есть ли скорость 0 - в этом случае у вас не будет выбора, кроме как использовать принятое решение для сохранения хранимых свойств.

Ответ 8

Для swift4

public func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if(scrollView.panGestureRecognizer.translation(in: scrollView.superview).y > 0) {
            print("up")
        }
        else {
            print("down")
        }
    }

Ответ 9

Я сделал протокол для повторного использования Scroll Directions.

Объявите эти enum и protocol s.

enum ScrollDirection {
    case up, left, down, right, none
}

protocol ScrollDirectionDetectable {
    associatedtype ScrollViewType: UIScrollView
    var scrollView: ScrollViewType { get }
    var scrollDirection: ScrollDirection { get set }
    var lastContentOffset: CGPoint { get set }
}

extension ScrollDirectionDetectable {
    var scrollView: ScrollViewType {
        return self.scrollView
    }
}

Использование из ViewController

// Set ScrollDirectionDetectable which has UIScrollViewDelegate
class YourViewController: UIViewController, ScrollDirectionDetectable {
    // any types that inherit UIScrollView can be ScrollViewType
    typealias ScrollViewType = UIScrollView
    var lastContentOffset: CGPoint = .zero
    var scrollDirection: ScrollDirection = .none

}
    extension YourViewController {
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            // Update ScrollView direction
            if self.lastContentOffset.x > scrollView.contentOffset.x {
                scrollDirection = .left
            } else if self.lastContentOffset.x > scrollView.contentOffset.x {
                scrollDirection = .right
            }

            if self.lastContentOffset.y > scrollView.contentOffset.y {
                scrollDirection = .up
            } else if self.lastContentOffset.y < scrollView.contentOffset.y {
                scrollDirection = .down
            }
            self.lastContentOffset.x = scrollView.contentOffset.x
            self.lastContentOffset.y = scrollView.contentOffset.y
        }
    }

Если вы хотите использовать определенное направление, просто обновите определенный contentOffset который вы хотите.

Ответ 10

Просто добавьте этот метод к вашему контроллеру представления:

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)
    }
}