Принудительно UITableView для прокрутки к верхам ячеек - PullRequest
10 голосов
/ 17 октября 2011

Есть ли способ заставить UITableViews прокручивать ячейку в ячейку?То есть вершина табличного представления всегда является вершиной UITableViewCell.

Я пробовал флаг подкачки, но это, кажется, прокручивает целые «страницы».Я просто хочу, чтобы ячейка прокручивалась.

Спасибо

Ответы [ 6 ]

20 голосов
/ 10 ноября 2011

UTTableView является подклассом UIScrollView, поэтому вы можете использовать метод scrollViewDidScroll для изменения позиции прокрутки TableView после прокрутки.

Вы можете использовать tableView.contentOffset, чтобы узнать, где находится ваша текущая позиция прокрутки. И, разделив его на осмысленное число, вы можете определить, какая ячейка находится сверху.

int cellIndex = tableView.contentOffset / cellHegiht;

Или вы можете получить видимую ячейку в центре (вверху, внизу) следующим образом:

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

После расчета, какая ячейка должна щелкнуть по ее краю сверху (или снизу), вы можете исправить отклонение от края ячейки, вызвав:

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

Вы можете использовать UIScrollViewDelegate методы для активации привязки. Вы можете активировать либо когда анимация прокрутки завершена, либо пока анимация продолжается. Это приведет к другому взаимодействию с пользователем и не скажет, что одно лучше другого.

Но реализация следующего метода и ничего более не похожа на мою любимую:

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

Этот метод вызывается, когда пользователь касается TableView, чтобы уведомить приложение. targetContentOffset - это переменная inout, поэтому вы можете установить конечную позицию прокрутки, пока анимация продолжается. Используя право cellHeight, ваш TableView всегда будет привязываться к ячейкам.

3 голосов
/ 02 сентября 2013

Если у вас есть разделы, я нашел этот самый надежный подход:

- (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 голос
/ 13 апреля 2014

Этот подход обрабатывает табличное представление с переменной высотой строки. Предполагается, что табличное представление имеет один раздел.

- (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];
}

Смещение вычисляется этим вспомогательным методом, который суммирует высоту всех строк над целевой строкой.

- (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;
}
1 голос
/ 13 февраля 2012

Хотя это и совершенно правильно, я не нашел ответ @randle очень полезным.Я прочитал документацию для разработчиков, и я был еще более смущен.Как бы то ни было, я наконец обнаружил, насколько простым был ответ, но иногда нам нужна небольшая, но большая помощь, чем «вызов этого метода».Смотрите под комментарием // прокрутите к строке!здесь:

- (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;
}

Теперь это для статической ячейки tableView.Я знаю количество строк, я знаю, какой ряд я собираюсь.Это может быть расширено до лучшего кода и программного доступа к переменным, но это показывает, КАК этот код работает на практике на низком уровне.

Я надеюсь, что это добавляет уровень полезности для всех, кто ищет форум.

Я сделал полное описание метода здесь: http://iosanswers.blogspot.com/2012/02/table-view-forms-scroll-to-selected.html

0 голосов
/ 24 октября 2015

Это хорошо работает, если у вас есть секции и строки со статической высотой.

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)
}
0 голосов
/ 10 ноября 2011

Вам просто нужно позвонить scrollToRowAtIndexPath:atScrollPosition:animated: и передать ему правильный путь индекса для нужной ячейки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...