在UITableView或UIScrollView中添加管理单元位置

时间:2014-01-06 00:07:34

标签: ios objective-c uitableview uiscrollview

是否可以在UITableView或UIScrollView中添加捕捉位置?我的意思是,如果我按下按钮或调用某种方法来自动滚动到某个位置,我的意思是如果我滚动滚动视图或桌面视图围绕特定点,比如0, 30,它将自动 - 抓住它并留在那里?因此,如果我的滚动视图或表格视图滚动,然后用户放在0, 250, 35之间,它会自动“捕捉”并滚动到那里?我可以想象可能会输入一个if语句来测试UIScrollView的scrollViewDidEndDragging:WillDecelerate:scrollViewWillBeginDecelerating:方法中该位置是否属于该区域但是我不确定如何在UITableView的。任何指导都将非常感谢。

7 个答案:

答案 0 :(得分:24)

就像Pavan所说,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;
}

答案 1 :(得分:6)

我劝你用 相反,scrollViewWillEndDragging: withVelocity: targetContentOffset:方法仅用于您的目的。将目标内容偏移设置为您想要的位置。

我还建议您查看已在SO上发布的重复问题。

Take a look at these posts

答案 2 :(得分:3)

在Swift 2.0中,当表格内容嵌入并简化时,ninefifteen's great answer变为:

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语句来增加索引。

答案 3 :(得分:3)

如果你真的必须手动执行此操作,这里是一个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

答案 4 :(得分:2)

这里是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

,这种复杂的舍入就完全没有必要了

答案 5 :(得分:1)

我相信如果你使用委托方法:

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

答案 6 :(得分:0)

即使单元格的高度可变(或未知),此代码也可以使您捕捉到单元格,如果您滚动到该行的下半部分,则可以捕捉到下一行,从而使其更“自然”

原始Swift 4.2代码:(为方便起见,这是我开发和测试的实际代码)

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    guard var scrollingToIP = table.indexPathForRow(at: CGPoint(x: 0, y: targetContentOffset.pointee.y)) else {
        return
    }
    var scrollingToRect = table.rectForRow(at: scrollingToIP)
    let roundingRow = Int(((targetContentOffset.pointee.y - scrollingToRect.origin.y) / scrollingToRect.size.height).rounded())
    scrollingToIP.row += roundingRow
    scrollingToRect = table.rectForRow(at: scrollingToIP)
    targetContentOffset.pointee.y = scrollingToRect.origin.y
}

(翻译的)Objective-C代码:(因为该问题被标记为objective-c

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    NSIndexPath *scrollingToIP = [self.tableView indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
    if (scrollingToIP == nil)
        return;
    CGRect scrollingToRect = [table rectForRowAtIndexPath:scrollingToIP];
    NSInteger roundingRow = (NSInteger)(round(targetContentOffset->y - scrollingToRect.origin.y) / scrollingToRect.size.height));
    scrollingToIP.row += roundingRow;
    scrollingToRect = [table rectForRowAtIndexPath:scrollingToIP];
    targetContentOffset->y = scrollingToRect.origin.y;
}