2011-10-17 15 views

Odpowiedz

20

UTTableView jest podklasą UIScrollView, dzięki czemu można używać scrollViewDidScroll metody, aby zmienić swoją pozycję przewijania Tableview po zwoju.

Możesz użyć numeru tableView.contentOffset, aby uzyskać aktualną pozycję przewijania. Dzieląc ją na znaczącą liczbę, możesz uzyskać komórkę na wierzchu.

int cellIndex = tableView.contentOffset/cellHegiht; 

Albo można dostać aktualnie widoczną komórki na środku (góra, dół), tak jak to:

NSArray *indexPathsForVisibleRows = [tableView indexPathsForVisibleRows]; 
NSIndexPath *selectedIndexPath = [indexPathsForVisibleRows objectAtIndex:(indexPathsForVisibleRows.count/2)]; //this gets center cell 

Po obliczeniu która komórka należy kliknąć jego krawędzi na górze (lub na dole) można skorygować dryf od krawędzi komórki przez wywołanie:

[tableView scrollToRowAtIndexPath:selectedIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

można użyć UIScrollViewDelegate sposobów aktywowania przyciągania. Możesz aktywować po zakończeniu przewijanej animacji lub gdy animacja będzie kontynuowana. To wygeneruje inną interakcję z użytkownikiem i nie może powiedzieć, że jeden jest lepszy od drugiego.

Ale wykonawczych następujące metody i nic poza tym wygląda na to będzie mój ulubiony:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView 
        withVelocity:(CGPoint)velocity 
       targetContentOffset:(inout CGPoint *)targetContentOffset { 
    int cellHeight = 41; 
    *targetContentOffset = CGPointMake(targetContentOffset->x, 
             targetContentOffset->y - (((int)targetContentOffset->y) % cellHeight)); 
} 

Metoda ta jest wywoływana, gdy użytkownik porusza się na TableView powiadomić aplikację. targetContentOffset to zmienna inout, dzięki czemu można ustawić końcową pozycję przewijania, podczas gdy animacja jest kontynuowana. Korzystając z prawa cellHeight, twoje TableView zawsze będzie przyciągało do komórek.

+2

Dzięki za pokazanie, jak używać zmiennej 'inout'. Bardzo fajna funkcja! – Besi

+0

+1 Dziękuję również, wskazując na zmienną "inout". – jpswain

+0

Z matmy - nigdy nie można przewinąć do ostatniego rzędu w tabeli ... nie jest to jednak problem. - zdecydowanie najlepsze rozwiązanie. – scottbates22

0

Po prostu trzeba zadzwonić pod numer scrollToRowAtIndexPath:atScrollPosition:animated: i przekazać mu właściwą ścieżkę indeksu dla wybranej komórki.

1

Chociaż całkowicie poprawne, nie znalazłem odpowiedzi przez @randle bardzo pomocne. Przeczytałem dokumentację dla programistów i byłem jeszcze bardziej zdezorientowany. Jak w końcu odkryłem, jak prosta jest odpowiedź, ale czasami potrzebujemy trochę więcej pomocy niż "wywołaj tę metodę". Zobacz pod komentarzem // przejdź do wiersza! tutaj:

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    if (textField == self.firstInput) { 
     [self.secondInput becomeFirstResponder]; 

     // scroll to row! 
     [self.tableView scrollToRowAtIndexPath: // use the method 
      [NSIndexPath indexPathForRow:1  // get 2nd row (nth row...) 
           inSection:0] // in 1st section (...) 
         // set position: you can use bottom, middle or top. 
         atScrollPosition:UITableViewScrollPositionBottom 
           animated:YES]; // YES or NO. 

    } else if (textField == self.secondInput) { 
     [textField resignFirstResponder]; 
    } 
    return YES; 
} 

To jest dla statycznego widoku komórki. Znam ilość rzędów, wiem, który wiersz mam zamiar. Mogłoby to zostać rozszerzone na lepszy kod i dostęp do zmiennych programowo, ale pokazuje, JAK ten kod działa w praktyce na niskim poziomie.

Mam nadzieję, że doda to warstwę użyteczności każdemu, kto przeszuka forum.

zrobiłem kompletny napisać metody tutaj: http://iosanswers.blogspot.com/2012/02/table-view-forms-scroll-to-selected.html

3

Jeśli masz sekcje, znalazłem to najbardziej wiarygodne podejście:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate(BOOL)decelerate { 
    if (decelerate == NO) { 
     [self autoAdjustScrollToTop]; 
    } 
} 
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    [self autoAdjustScrollToTop]; 
} 
- (void)autoAdjustScrollToTop { 
    // compare the top two visible rows to the current content offset 
    // and auto scroll so that the best row is snapped to top 
    NSArray *visibleRows = [self.tableView indexPathsForVisibleRows]; 
    NSIndexPath *firstPath = visibleRows[0]; 
    NSIndexPath *secondPath = visibleRows[1]; 
    CGRect firstRowRect = [self.tableView rectForRowAtIndexPath:firstPath]; 
    [self.tableView scrollToRowAtIndexPath:(firstRowRect.origin.y > self.tableView.contentOffset.y ? firstPath : secondPath) atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
} 
1

Podejście obsługuje widok tabeli z różnych wysokościach rzędu . Zakłada on, że widok tabeli ma jedną sekcję.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView 
        withVelocity:(CGPoint)velocity 
       targetContentOffset:(inout CGPoint *)targetContentOffset { 

    // Find the row where the animation will currently end. 
    NSInteger targetRow = [[self.tableView indexPathForRowAtPoint:*targetContentOffset] row]; 

    // Tell the animation to end at the top of that row. 
    *targetContentOffset = [self offsetForTopOfRow:targetRow]; 
} 

Przesunięcie jest obliczane za pomocą tej metody pomocniczej, która sumuje wysokości wszystkich rzędów powyżej wiersza docelowego.

- (CGPoint)offsetForTopOfRow:(NSInteger)row { 

    CGPoint offset = CGPointZero; 

    for (int i = 0; i < row; i++) { 
     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0]; 
     CGFloat height = [self.tableView.delegate tableView:self.tableView heightForRowAtIndexPath:indexPath]; 
     offset.y += height; 
    } 

    return offset; 
} 
0

Działa to dobrze, jeśli masz sekcje i rzędy o statycznych wysokościach.

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { 
    // Adjust target offset so that cells are snapped to top 
    let cellHeight: CGFloat = 44 
    let headerHeight: CGFloat = 30 
    let section = (indexPathsForVisibleRows?.first?.section ?? 0) + 1 
    targetContentOffset.memory.y -= (targetContentOffset.memory.y % cellHeight) - (CGFloat(sectionIndex) * headerHeight) 
} 
Powiązane problemy