webentwicklung-frage-antwort-db.com.de

Wie erreiche ich die vertikale Richtung von UIScrollView in Swift?

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.

19
user2722667

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.

69
Victor Sigler

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. ???? 

29
GLS

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

Swift 2-4 mit UISwipeGestureRecognizer

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")
        }
    }
}
2
Daniel Krom

Für Swift4

public func scrollViewDidScroll(_ scrollView: UIScrollView) {

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

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.

1
brandonscript

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

1
Sasho

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
}
1
Felipe Rolvar

Ich habe ein Protokoll erstellt, um die Scroll-Anweisungen wiederzuverwenden.

Deklarieren Sie diese enum und protocols.

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.

0
Changnam Hong

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
}
0
Petros Mitakos

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)
    }
}
0
Archi Stepanov