Принудительно UITableView для прокрутки к верхам ячеек

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

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

Спасибо

6 ответов

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 всегда будет привязываться к клеткам.

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

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

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

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

Несмотря на то, что я полностью согласен, я не нашел ответ @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

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

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

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)
}
Другие вопросы по тегам