UIScrollView. Jakieś pomysły na implementację" nieskończonego " przewijania / powiększania?

Tak więc UITableView obsługuje zasadniczo" nieskończone " przewijanie. Nie może być limit ale ten frajer może przewijać przez looonnnggg czas. Chciałbym naśladować to zachowanie za pomocą UIScrollView, ale istnieją dwie podstawowe przeszkody:

1) scrollView.contentSize jest ustalany w czasie tworzenia. 2) powiększanie może wysadzić każdy leniwy schemat ładowania do piekła, ponieważ może spowodować nieskończoną eksplozję danych.

Czy inni zastanawiali się nad tym pomysłem? Tak, Wiem, w zasadzie rozmawiamy. o ponownym tworzeniu map Google tutaj. Wszelkie spostrzeżenia będą mile widziane.

Cheers, Doug

Author: dugla, 2009-09-29

5 answers

Chociaż niemożliwe jest posiadanie prawdziwie nieskończonego widoku UIScrollView, istnieje kilka prostych sztuczek, których możesz użyć, aby naśladować to zachowanie.

  1. Obsługa naprawionego contentSize: Ustaw widok o stałym rozmiarze obsługiwany przez widok przewijania, a podczas uruchamiania lub tworzenia instancji Ustaw przesunięcie zawartości tak, aby było widoczne pośrodku obsługiwanego widoku. Następnie po prostu obserwuj przesunięcie zawartości (za pomocą KVO lub innej metody), a jeśli zbliżysz się do dowolnej krawędzi, zaktualizuj zawartość widoku nowym zestawem zawartości (przesuń odpowiednio) i zresetuj Właściwość contentOffset widoku przewijania, aby była z powrotem w środku.
  2. Obsługa powiększania: zrób coś podobnego, tylko tym razem obserwuj współczynnik powiększenia w widoku przewijania. Gdy dojdzie do pewnego punktu, wykonaj manipulację dowolnymi prezentowanymi danymi, aby wyglądały one powiększone, a następnie zresetuj współczynnik powiększenia do 1.0. Na przykład, jeśli przewijasz obraz, który zostanie powiększony, aby był dwukrotnie większy, programowo zastosuj jakąś transformację, aby obraz dwa razy większy, a następnie zresetuj współczynnik powiększenia widoku przewijania do 1,0. Obraz będzie nadal wyświetlany w powiększeniu, ale widok przewijania będzie mógł kontynuować powiększanie w razie potrzeby. (Google Maps idzie o krok dalej, gdzie leniwy-ładuje bardziej szczegółowe widoki w miarę powiększania użytkownika - Możesz lub nie możesz zdecydować się na wdrożenie tego.)
 10
Author: Tim,
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
2009-09-29 17:49:37

Właśnie skończyłem implementować zwój infitine. W mojej implementacji mam UITableViewCell z przewijaniem i przyciskami nawigacyjnymi. Widok przewijania zawiera widoki x o tej samej szerokości. widoki są wyrównywane poziomo, a stronicowanie jest włączone.

scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;

Mój codelogic wygląda następująco:

  1. w mojej funkcji inicjalizacyjnej I
    • tworzy wszystkie widoki (dla widoku przewijania) i
    • umieścić je w tablicy i
    • dodaj je do scrollView
  2. Następnie wywołuję funkcję, która oblicza w pętli pozycje dla każdego widoku(za każdym razem, gdy wykryjesz przewijanie, ta funkcja będzie musiała zostać wywołana). Zawsze pobiera pierwszy element tablicy i ustawia ramkę na (0,0,...,...), drugi z (i * szerokość, 0,....,....) i tak dalej. Wywołana funkcja wygląda tak:

    - (void)updateOffsetsOfViews{
        int xpos = 0;
        for (int i=0; i<[views count]; i++) {
            UIImageView *_view = [views objectAtIndex:i];
            CGRect aFrame = _view.frame;
            aFrame.origin.x = xpos;
            aFrame.origin.y = 0.0;
            _view.frame = aFrame;
            xpos += viewWidth;
        }
        float center = 0;
        if(fmod([views count],2) == 1){
            center = viewWidth * ([views count]-1)/2;
        }else {
            center = viewWidth * [views count]/2;
        }
        [scrollView setContentOffset:CGPointMake(center, 0)];
        lastOffset = center;
    }
    
  3. Następnie (jeszcze w procesie inicjalizacji) dodaję obserwatora

    [scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:nil];
    

    Więc za każdym razem coś w scrollView zmienia mi się (observeValueForKeyPath)-wywołana funkcja, która wygląda tak:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object  change:(NSDictionary *)change context:(void *)context
    {
        UIImageView *_viewFirst = (UIImageView *)[views objectAtIndex:0];
        if ( fmod([scrollView contentOffset].x,viewWidth)  == 0.0) {
            if ([scrollView contentOffset].x > lastOffset) {
                [views removeObjectAtIndex:0];
                [views addObject:_viewFirst];                
                [self updateOffsetsOfViews];    
            }else if ([scrollView contentOffset].x < lastOffset) {
                UIImageView *_viewLast = (UIImageView *)[views lastObject];
                [views removeLastObject];
                [views insertObject:_viewLast atIndex:0];            
                [self updateOffsetsOfViews];
            }
        }
    }
    
  4. A w dealloc lub viewDidUnload (zależy od tego jak to zaimplementujesz) nie zapomnij usunąć obserwatora.

    [scrollView removeObserver:self forKeyPath:@"contentOffset"];   
    

Mam nadzieję, że to pomoże, możesz zauważyć pewne koszty, ale w mojej implementacji popieram również przewijanie 5 stron (dobrze ... nieograniczone) na raz i autoanimowane przewijanie itp. więc możesz zobaczyć coś, co można rzucić daleko.

 13
Author: Allisone,
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
2010-07-02 13:23:22

Przykładowy projekt StreetScroller firmy Apple pokazuje, jak wykonywać nieskończone przewijanie w widoku UIScrollView.

 4
Author: michaelhanson,
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-09-05 22:26:11

Pamiętaj, że gdy przewijanie jest animowane, contentOffset zmienia się wiele razy, nie tylko strona po stronie, ale z każdym krokiem animacji.

 2
Author: user439139,
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-02-15 11:09:53

Być może ustawienie contentSize Na jakąś gigantyczną wartość, a następnie przesunięcie ograniczonej liczby podstawowych widoków wokół, aby śledzić pozycję widoku, jak w próbce kafelków, wystarczy.

Aby zminimalizować możliwość osiągnięcia krawędzi i konieczności nagłego cofnięcia widoku (co anuluje przewijanie aktualnie w ruchu), Widok może być od czasu do czasu Cofnięty, gdy jest nieruchomy.

Tak czy siak, właśnie tego zamierzam spróbować.
 0
Author: Grumdrig,
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
2010-04-05 21:41:53