Jak uzyskać kierunek pionowy UIScrollView w języku Swift?

Jak mogę uzyskać kierunek przewijania / przesuwania w górę / w dół w VC?

Chcę dodać UIScrollView lub coś innego w moim VC, który może zobaczyć, czy użytkownik przesuwa / przewija w górę lub w dół, a następnie ukryć / pokazać UIView w zależności od tego, czy był to gest góra/dół.

Author: Moritz, 2015-08-06

9 answers

Jeśli używasz UIScrollView to możesz skorzystać z scrollViewDidScroll: funkcja. Musisz zapisać ostatnią pozycję (contentOffset), którą ma i zaktualizować ją w następujący sposób:

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

Są inne sposoby, aby to zrobić, oczywiście, że jest to jeden z nich.

Mam nadzieję, że to ci pomoże.
 62
Author: Victor Sigler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 13:36:52

Odpowiedź Victora jest świetna, ale jest dość droga, ponieważ zawsze porównujesz i przechowujesz wartości. Jeśli twoim celem jest natychmiastowe określenie kierunku przewijania bez kosztownych obliczeń, spróbuj tego za pomocą 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
    }
}
No i proszę. Ponownie, jeśli trzeba śledzić stale, użyj Winktory odpowiedzieć, w przeciwnym razie wolę to rozwiązanie.
 24
Author: GLS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 22:15:17

Użyłem odpowiedzi Victora z drobną poprawką podczas przewijania końca lub początku przewijania, a następnie uzyskiwania efektu odbicia. Dodałem ograniczenie obliczając (scrollView.contentSize.wysokość-scrollView.rama.wysokość), a następnie ograniczenie widoku przewijania.contentOffset.zakres y ma być większy niż 0 lub mniejszy niż (scrollView.contentSize.wysokość-scrollView.rama.wysokość), nie ma żadnych zmian podczas odbijania.

 //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`
 3
Author: gbotha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-27 17:05:16

Swift 2-4 z UISwipeGestureRecognizer

Inną opcją jest użycie UISwipeGestureRecognizer, które rozpozna przesunięcie w żądany kierunek (które będzie działać na wszystkich widokach, a nie tylko na 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")
        }
    }
}
 2
Author: Daniel Krom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 05:19:31

Dla Swift myślę, że najprostszym i najpotężniejszym jest zrobić jak poniżej. Pozwala śledzić, gdy kierunek zmienił się i reagować tylko raz, gdy się zmienił. Dodatkowo możesz zawsze uzyskać dostęp do Właściwości .lastDirection scrolled, jeśli chcesz to sprawdzić w kodzie na dowolnym innym etapie.

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

Powyższe zakłada, że śledzisz tylko przewijanie w górę / w dół. Jest konfigurowalny za pomocą enum. Możesz dodać / zmienić na .left i .right, aby śledzić dowolny kierunek.

Mam nadzieję, że to pomoże ktoś.

Cheers

 1
Author: Sasho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 08:14:34

Mógłbyś zrobić coś takiego:

fileprivate var lastContentOffset: CGPoint = .zero

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

Oraz z scrollViewDelegate:

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

    lastContentOffset = scrollView.contentOffset
}
 1
Author: Felipe Rolvar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 22:51:55

Odkryłem, że jest to najprostsza i najbardziej elastyczna opcja(działa również dla UICollectionView i 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
    }
}

Gdzie to nie działa, to jeśli istnieje 0 velocity - w takim przypadku nie będziesz miał wyboru, jak tylko użyć rozwiązania przechowywanej właściwości zaakceptowanej odpowiedzi.

 1
Author: brandonscript,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-21 03:47:17

Zrobiłem protokół ponownego użycia wskazówek zwoju.

Zadeklaruj te enum i 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
    }
}

Użycie Z 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
        }
    }

Jeśli chcesz użyć określonego kierunku, po prostu zaktualizuj określone contentOffset, które chcesz.

 0
Author: Changnam Hong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 05:08:22

Dla swift4

public func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if(scrollView.panGestureRecognizer.translation(in: scrollView.superview).y > 0) {
            print("up")
        }
        else {
            print("down")
        }
    }
 0
Author: Hardik Thakkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-14 11:01:29