Wie kann ich die Bildlauf-/Wischrichtung für einen VC nach oben/unten berechnen?
Ich möchte ein UIScrollView oder etwas anderes in meinem VC hinzufügen, das sehen kann, ob der Benutzer nach oben oder unten wischt/scrollen und dann eine UIView
ein-/ausblenden, je nachdem, ob es sich um eine Auf-/Ab-Geste handelt.
Wenn Sie eine UIScrollView
verwenden, können Sie die Funktion scrollViewDidScroll:
nutzen. Sie müssen die letzte Position (die contentOffset
) und die Aktualisierung wie folgt speichern:
// 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
}
Es gibt andere Wege, dies zu tun.
Ich hoffe das hilft dir.
Die Antwort von Victor ist großartig, aber es ist ziemlich teuer, da Sie immer Werte vergleichen und speichern. Wenn Sie die Bildlaufrichtung ohne kostspielige Berechnung sofort ermitteln möchten, versuchen Sie dies mit 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
}
}
Und los gehts. Wenn Sie ständig verfolgen müssen, verwenden Sie die Antwort von Victors, ansonsten bevorzuge ich diese Lösung. ????
Ich habe die Antwort von Victor mit einer kleinen Verbesserung verwendet. Wenn Sie am Ende oder am Anfang des Bildlaufs vorbeirollen und dann den Bounce-Back-Effekt erhalten. Ich habe die Einschränkung hinzugefügt, indem ich scrollView.contentSize.height - scrollView.frame.height
berechnete und dann den scrollView.contentOffset.y
-Bereich auf einen Wert größer als 0 oder weniger als scrollView.contentSize.height - scrollView.frame.height
einschränkte. Beim Zurückspringen werden keine Änderungen vorgenommen.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if lastContentOffset > scrollView.contentOffset.y && lastContentOffset < scrollView.contentSize.height - scrollView.frame.height {
// move up
} else if lastContentOffset < scrollView.contentOffset.y && scrollView.contentOffset.y > 0 {
// move down
}
// update the new position acquired
lastContentOffset = scrollView.contentOffset.y
}
Eine andere Option ist die Verwendung der Option UISwipeGestureRecognizer
, die den Swipe in die angeforderte Richtung erkennt (das funktioniert bei allen Ansichten und nicht nur bei 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")
}
}
}
Für Swift4
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if(scrollView.panGestureRecognizer.translation(in: scrollView.superview).y > 0) {
print("up")
}
else {
print("down")
}
}
Ich habe festgestellt, dass dies die einfachste und flexibelste Option ist (sie funktioniert auch für UICollectionView und 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
}
}
Wo dies nicht funktioniert, ist es, wenn die Geschwindigkeit 0 ist. In diesem Fall haben Sie keine andere Wahl, als die gespeicherte Eigenschaftslösung der akzeptierten Antwort zu verwenden.
Für Swift Ich denke, die einfachste und mächtigste ist es, wie unten zu tun. Damit können Sie verfolgen, wann sich die Richtung geändert hat, und nur einmal reagieren, wenn sie geändert wurde . Außerdem können Sie jederzeit auf die .lastDirection
scrolled -Eigenschaft zugreifen, wenn Sie dies in Ihrem Code zu einem anderen Zeitpunkt aufrufen müssen.
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
}
}
}
}
Die obigen Angaben gehen davon aus, dass Sie nur den Bildlauf nach oben/unten verfolgen. __, der über die Aufzählung anpassbar ist. Sie können .left
und .right
hinzufügen/ändern, um eine beliebige Richtung zu verfolgen.
Ich hoffe das hilft jemandem.
Prost
sie könnten so etwas tun:
fileprivate var lastContentOffset: CGPoint = .zero
func checkScrollDirection(_ scrollView: UIScrollView) -> UIScrollViewDirection {
return lastContentOffset.y > scrollView.contentOffset.y ? .up : .down
}
und mit scrollViewDelegate:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
switch checkScrollDirection(scrollView) {
case .up:
// move up
case .down:
// move down
default:
break
}
lastContentOffset = scrollView.contentOffset
}
Ich habe ein Protokoll erstellt, um die Scroll-Anweisungen wiederzuverwenden.
Deklarieren Sie diese enum
und 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
}
}
Verwendung von 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
}
}
Wenn Sie eine bestimmte Richtung verwenden möchten, aktualisieren Sie einfach die gewünschte contentOffset
.
Ich habe jede einzelne Antwort in diesem Thread ausprobiert, aber keine davon konnte eine geeignete Lösung für eine TableView mit aktiviertem Bounce bereitstellen. Also habe ich nur Teile von Lösungen zusammen mit einigen klassischen booleschen Flaggen aller Zeiten verwendet.
1) Sie können also zunächst ein Enum für die scrollDirection verwenden:
enum ScrollDirection {
case up, down
}
2) Legen Sie 3 neue private Variablen fest, die uns beim Speichern von lastOffset, scrollDirection und einem Flag zum Aktivieren/Deaktivieren der Bildlaufrichtungsberechnung helfen.
private var shouldCalculateScrollDirection = false
private var lastContentOffset: CGFloat = 0
private var scrollDirection: ScrollDirection = .up
3) Fügen Sie im scrollViewDidScroll Folgendes hinzu:
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) Wenn Sie scrollViewDidEndDragging nicht implementiert haben, implementieren Sie es und fügen Sie die folgenden Codezeilen hinzu:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
guard !decelerate else { return }
shouldCalculateScrollDirection = false
}
5) Wenn Sie scrollViewWillBeginDecelerating nicht implementiert haben, implementieren Sie es und fügen Sie diese Codezeile hinzu:
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
shouldCalculateScrollDirection = false
}
6) Wenn Sie scrollViewWillBeginDragging noch nicht implementiert haben, implementieren Sie es und fügen Sie diese Codezeile hinzu:
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
shouldCalculateScrollDirection = true
}
Und wenn Sie alle oben genannten Schritte befolgt haben, können Sie gut gehen!
Sie können dorthin gehen, wo Sie die Richtung verwenden möchten, und schreiben Sie einfach:
switch scrollDirection {
case .up:
// Do something for scollDirection up
case .down:
// Do something for scollDirection down
}
Fügen Sie diese Methode einfach zu Ihrem view Controller hinzu:
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)
}
}