Wykrywanie zmiany strony UIScrollView
Czy istnieje sposób na wykrycie lub otrzymanie powiadomienia, gdy użytkownik zmienia stronę w uiscrollview z obsługą stronicowania?
10 answers
Zaimplementuj delegata UIScrollView. ta metoda jest tym, czego szukasz.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
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
2011-03-11 11:20:25
Użyj tego, aby wykryć, która strona jest aktualnie wyświetlana i wykonać pewną akcję przy zmianie Strony:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
static NSInteger previousPage = 0;
CGFloat pageWidth = scrollView.frame.size.width;
float fractionalPage = scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
if (previousPage != page) {
// Page has changed, do your thing!
// ...
// Finally, update previous page
previousPage = page;
}
}
Jeśli akceptowalne jest reagowanie na zmianę strony dopiero po całkowitym zatrzymaniu przewijania, najlepiej byłoby wykonać powyższe czynności wewnątrz metody delegowania scrollViewDidEndDecelerating:
zamiast metody scrollViewDidScroll:
.
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
2014-04-01 09:25:37
W paging enabled scroll view możesz użyć scrollViewDidEndDecelerating, aby wiedzieć, kiedy widok jest rozliczany na stronie (może to być ta sama strona).
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
scrollViewDidScroll
jest wzywany na każdy ruch. A w kontekście stronicowania włączony Widok może być używany do znalezienia, kiedy jest przewijany na tyle, aby przejść do następnej strony (jeśli przeciąganie jest zatrzymane w tym momencie).
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
2012-04-07 16:01:55
Jak o połączeniu dwóch metod UIScrollViewDelegate?
W scrollViewDidEndDragging(_:willDecelerate:)
, jeśli zatrzyma się od razu, wykonujemy obliczenia strony; jeśli zwalnia, odpuszczamy go i zostanie złapany przez scrollViewDidEndDecelerating(_:)
.
Kod jest testowany z Xcode w wersji 7.1.1, Swift w wersji 2.1
class ViewController: UIViewController, UIScrollViewDelegate {
// MARK: UIScrollViewDelegate
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate == false {
let currentPage = scrollView.currentPage
// Do something with your page update
print("scrollViewDidEndDragging: \(currentPage)")
}
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let currentPage = scrollView.currentPage
// Do something with your page update
print("scrollViewDidEndDecelerating: \(currentPage)")
}
}
extension UIScrollView {
var currentPage: Int {
return Int((self.contentOffset.x+ (0.5*self.frame.size.width))/self.frame.width)+1
}
}
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-26 17:16:02
Pierwszy wynik w google dla wykrywania strony, więc musiałem odpowiedzieć na to lepszym rozwiązaniem moim zdaniem. (nawet jeśli pytanie to zostało zadane 2 i pół roku temu.)
Wolałbym nie dzwonić, żeby śledzić numer strony. To przesada dla czegoś prostego. UżyciescrollViewDidEndDecelerating
działa i zatrzymuje się na zmianie Strony ale (i to duże ale) jeśli użytkownik przesunie palcem po ekranie dwa razy nieco szybciej niż normalnie scrollViewDidEndDecelerating
zostanie wywołany tylko raz. Możesz łatwo przejść od strona # 1 do strony #3 bez przetwarzania strony # 2.
To rozwiązało to całkowicie dla mnie:
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
scrollView.userInteractionEnabled = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
//Run your code on the current page
scrollView.userInteractionEnabled = YES;
}
W ten sposób użytkownik może przesuwać tylko jedną stronę na raz bez ryzyka opisanego powyżej.
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
2014-10-20 13:04:27
Swift 4
Uznałem, że najlepszym sposobem na to jest użycie scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)
. Pozwala przewidzieć, czy stronicowanie pojawi się zaraz po uniesieniu palca z ekranu. Ten przykład dotyczy stronicowania poziomego.
Pamiętaj o przypisaniu {[2] } do obiektu, który przyjmuje UIScrollViewDelegate
i implementuje tę metodę.
var previousPageXOffset: CGFloat = 0.0
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetOffset = targetContentOffset.pointee
if targetOffset.x == previousPageXOffset {
// page will not change
} else if targetOffset.x < previousPageXOffset {
// scroll view will page left
} else if targetOffset.x > previousPageXOffset {
// scroll view will page right
}
previousPageXOffset = targetOffset.x
// If you want to track the index of the page you are on just just divide the previousPageXOffset by the scrollView width.
// let index = Int(previousPageXOffset / scrollView.frame.width)
}
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-03-27 17:54:11
Oto szybkie rozwiązanie tego problemu.
Utwórz dwie właściwości currentPage i previousPage w klasie, w której implementujesz kod i zainicjalizuj je na 0.
Teraz zaktualizuj currentPage z scrollViewDidEndDragging (: willDecelerate:) i scrollViewDidEndDecelerating (: scrollView:).
A następnie zaktualizuj previousPage w scrollViewDidEndScrollingAnimation (_: scrollView:)
//Class Properties
var currentPage = 0
var previousPage = 0
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
updatePage(scrollView)
return
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
updatePage(scrollView)
return
}
func updatePage(scrollView: UIScrollView) {
let pageWidth:CGFloat = scrollView.frame.width
let current:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1
currentPage = Int(current)
if currentPage == 0 {
// DO SOMETHING
}
else if currentPage == 1{
// DO SOMETHING
}
}
func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
if previousPage != currentPage {
previousPage = currentPage
if currentPage == 0 {
//DO SOMETHING
}else if currentPage == 1 {
// DO SOMETHING
}
}
}
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-03-22 10:25:00
Wytnij i wklej na rok 2019]}
Nie jest tak łatwo to zrobić:
var quantumPage: Int = -100 { // the UNIQUELY LANDED ON, NEVER REPEATING page
didSet {
print(">>>>>> QUANTUM PAGE IS \(quantumPage)")
pageHasActuallyChanged() // your function
}
}
private var possibleQuantumPage: Int = -100 {
didSet {
if oldValue != possibleQuantumPage {
quantumPage = possibleQuantumPage
}
}
}
public func scrollViewDidEndDragging(
_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate == false {
possibleQuantumPage = currentPageEvenIfInBetween
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
possibleQuantumPage = currentPageEvenIfInBetween
}
var currentPageEvenIfInBetween: Int {
return Int((self.contentOffset.x + (0.5 * self.frame.width)) / self.frame.width)
}
Działa idealnie.
pageHasActuallyChanged
Wola tylko być wywołane, gdy użytkownik zmienia strony w tym, co ludzie uważają za "zmienianie stron".
Bądź świadomy: bringup jest trudny:
To jest trudne do zainicjowania w czasie bringup, a to zależy od tego, jak używasz systemu paged .W każdym systemie paged najprawdopodobniej będziesz miał coś takiego "scrollToViewAtIndex..."
open func scrollToViewAtIndexForBringup(_ index: Int) {
if index > -1 && index < childViews.count {
let w = self.frame.size.width
let h = self.frame.size.height
let frame = CGRect(x: CGFloat(index)*w, y: 0, width: w, height: h)
scrollRectToVisible(frame, animated: false) // NOTE THE FALSE
// AND IMPORTANTLY:
possibleQuantumPage = currentPageEvenIfInBetween
}
}
Więc, jeśli użytkownik otworzy "książkę" na stronie 17, w klasie szefa będziesz wywoływał tę funkcję, aby ustawić ją na" 17 " przy bringup.
W takim przykładzie, musisz tylko pamiętać, że musi Ustaw wstępnie naszą możliwą wartość quantumpage w takich funkcjach bringup; nie ma naprawdę uogólnionego sposobu na poradzenie sobie z sytuacją początkową.
W końcu możesz, na przykład, chclno aby "szybko przewijać" do strony bringup, a kto wie, co to "oznacza" w sytuacji quantumPage. Pamiętaj więc, aby starannie zainicjować swój system stron kwantowych podczas bringup, w oparciu o swoją sytuację.
W każdym razie, po prostu skopiuj i wklej pięć funkcji na górze, aby uzyskać doskonałe przywoływanie kwantowe.
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
2020-06-20 09:12:55
Dla Swift
static var previousPage: Int = 0
func scrollViewDidScroll(_ scrollView: UIScrollView){
let pageWidth: CGFloat = scrollView.frame.width
let fractionalPage: CGFloat = scrollView.contentOffset.x / pageWidth
let page = lround(Double(fractionalPage))
if page != previousPage{
print(page)
// page changed
}
}
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
2020-01-08 14:09:02
var scrollViewPage = 0
override func viewDidLoad() {
super.viewDidLoad()
scrollViewPage = scrollView.currentPage
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollViewPage != scrollView.currentPage {
scrollViewPage = scrollView.currentPage
// Do something with your page update
print("scrollViewDidEndDecelerating: \(scrollViewPage)")
}
}
I użyj rozszerzenia
extension UIScrollView {
var currentPage: Int {
return Int((self.contentOffset.x + (0.5 * self.frame.size.width)) /
self.frame.width) + 1
}
}
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
2020-09-11 10:28:54