Добавить привязку к позиции в UITableView или UIScrollView

Можно ли добавить привязку в UITableView или UIScrollView? То, что я имею в виду, это не автоматический прокрутка к позиции, если я нажимаю кнопку или вызываю какой-либо метод, чтобы сделать это, я имею в виду, если я прокручу свое представление прокрутки или табличное представление вокруг определенной точки, скажем 0, 30, он автоматически привяжется к это и остаться там? Поэтому, если свиток или просмотр таблицы прокручиваются, а затем пользователь может войти между 0, 25 или 0, 35, он будет автоматически "привязываться" и прокручиваться там? Я могу представить себе, может быть, вставить if-инструкцию, чтобы проверить, попадает ли позиция в эту область в методы scrollViewDidEndDragging:WillDecelerate: или scrollViewWillBeginDecelerating: UIScrollView, но я не уверен, как это реализовать в случае UITableView. Любое руководство будет высоко оценено.

Ответ 1

Как сказал Паван, scrollViewWillEndDragging: withVelocity: targetContentOffset: это метод, который вы должны использовать. Он работает с видами таблиц и прокруткой. Приведенный ниже код должен работать для вас, если вы используете представление таблицы или вертикальное прокручивание прокрутки. 44.0 - это высота ячеек таблицы в образце кода, поэтому вам нужно будет настроить это значение на высоту ваших ячеек. Если используется для прокрутки в горизонтальном прокрутке, замените y на x и измените 44.0 на ширину отдельных разделов в режиме прокрутки.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    // Determine which table cell the scrolling will stop on.
    CGFloat cellHeight = 44.0f;
    NSInteger cellIndex = floor(targetContentOffset->y / cellHeight);

    // Round to the next cell if the scrolling will stop over halfway to the next cell.
    if ((targetContentOffset->y - (floor(targetContentOffset->y / cellHeight) * cellHeight)) > cellHeight) {
        cellIndex++;
    }

    // Adjust stopping point to exact beginning of cell.
    targetContentOffset->y = cellIndex * cellHeight;
}

Ответ 2

Я призываю вас использовать scrollViewWillEndDragging: withVelocity: targetContentOffset:, который предназначен для вашей цели. для установки смещения целевого содержимого в желаемое положение.

Я также предлагаю вам посмотреть на дублированные вопросы, уже опубликованные на SO.

Взгляните на эти сообщения

Ответ 3

В Swift 2.0, когда таблица имеет вставку содержимого и упрощает, девять пятнадцати замечательных ответов становится:

func scrollViewWillEndDragging(scrollView:            UIScrollView,
                               withVelocity velocity: CGPoint,
                               targetContentOffset:   UnsafeMutablePointer<CGPoint>)
{
    let cellHeight = 44
    let y          = targetContentOffset.memory.y + scrollView.contentInset.top + cellHeight / 2
    var cellIndex  = floor(y / cellHeight)

    targetContentOffset.memory.y = cellIndex * cellHeight - scrollView.contentInset.top;
}

Просто добавив cellHeight / 2, девятикратное if -statement для увеличения индекса больше не требуется.

Ответ 4

Если вы действительно должны сделать это вручную, вот версия Swift3. Тем не менее, настоятельно рекомендуется просто включить пейджинг для UITableView, и это уже обрабатывается для вас.

let cellHeight = 139
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    targetContentOffset.pointee.y = round(targetContentOffset.pointee.y / cellHeight) * cellHeight
}

// Or simply
self.tableView.isPagingEnabled = true

Ответ 5

Здесь эквивалент Swift 2.0

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let cellWidth = CGRectGetWidth(frame) / 7   // 7 days
    var index = round(targetContentOffset.memory.x / cellWidth)
    targetContentOffset.memory.x = index * cellWidth
}

И это сложное округление не требуется вообще, если вы используете round вместо floor

Ответ 6

Я считаю, что если вы используете метод делегата:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    NSLog(@"%f",scrollView.contentOffset.y);
    if (scrollView.contentOffset.y > 350 && scrollView.contentOffset.y < 370)
    {
        NSLog(@"setContentOffset");
        [scrollView setContentOffset:CGPointMake(0, 350) animated:YES];
    }
}

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

Причина этого: if (scrollView.contentOffset.y > 350 && scrollView.contentOffset.y < 370) заключается в том, что просмотр прокрутки вызывает scrollViewDidScroll при перескакивании на быстрых скоростях, поэтому я даю между if.

Вы также можете знать, что скорость замедляется:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"%f",scrollView.contentOffset.y);
    int scrollSpeed = abs(scrollView.contentOffset.y - previousScrollViewYOffset);
    previousTableViewYOffset = scrollView.contentOffset.y;
    if (scrollView.contentOffset.y > 350 && scrollView.contentOffset.y < 370 && scrollSpeed < minSpeedToStop)
    {
        NSLog(@"setContentOffset");
        [scrollView setContentOffset:CGPointMake(0, 350) animated:YES];
    }
}