永恒滚动UITableView

时间:2011-09-20 15:02:11

标签: objective-c cocoa-touch uitableview scroll

我正在尝试使用日期创建一个UITableView,不应该非常令人兴奋,我知道。它从当前日期开始,但用户应该能够向下(未来)向上(过去)向他/她想要。这导致可能无限数量的行。那么创建它的方法是什么?

返回NSIntegerMax因为行数已经崩溃了应用程序,但即使它不会,但仍然不能解释能够滚动向上。我当然可以从中途开始,但最终会有一个最大值。

任何想法怎么做或假冒这个?我可以在没有用户注意的情况下以某种方式更新/重新加载表格,所以我从未碰到边界吗?

SOLUTION:
我按照@ ender的建议去做了一个固定数量的细胞的桌子。但是当用户滚动到固定单元格的边缘附近时,我没有重新加载它,而是在滚动停止时重新加载表格。为了适应用户不停地滚动很远的距离,我只是将行数增加到1000,将ROW_CENTER常量设置为500.这是负责更新行的方法。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray *visible = [self.tableView indexPathsForVisibleRows];
    NSIndexPath *upper = [visible objectAtIndex:0];
    NSIndexPath *lower = [visible lastObject];

    // adjust the table to compensate for the up- or downward scrolling
    NSInteger upperDiff = ROW_CENTER - upper.row;
    NSInteger lowerDiff = lower.row - ROW_CENTER;

    // the greater difference marks the direction we need to compensate
    NSInteger magnitude = (lowerDiff > upperDiff) ? lowerDiff : -upperDiff;

    self.offset += magnitude;
    CGFloat height = [self tableView:self.tableView heightForRowAtIndexPath:lower];
    CGPoint current = self.tableView.contentOffset;
    current.y -= magnitude * height;
    [self.tableView setContentOffset:current animated:NO];

    NSIndexPath *selection = [self.tableView indexPathForSelectedRow];
    [self.tableView reloadData];
    if (selection)
    {
        // reselect a prior selected cell after the reload.
        selection = [NSIndexPath indexPathForRow:selection.row - magnitude inSection:selection.section];
        [self.tableView selectRowAtIndexPath:selection animated:NO scrollPosition:UITableViewScrollPositionNone];
    }
}

当用户在不停止的情况下滚动到桌面边缘时,魔术会中断,但禁用表格视图bounces属性,这只是一个小故障,但完全可以接受。一如既往,感谢StackOverflow!

5 个答案:

答案 0 :(得分:5)

当用户滚动到tableview的末尾附近时,您应该建立固定数量的单元格并调整数据源。例如,您有一个包含51个日期的数组(今天,25个未来和25个过去)。当应用尝试在其中一个边框附近渲染单元格时,请重新配置阵列并调用reloadData

答案 1 :(得分:3)

您可能还会看一下WWDC 2011的“高级滚动视图技术”演讲。他们展示了如何创建一个无限滚动的UIScrollView。它开始于约5分钟。英寸

答案 2 :(得分:2)

两个想法:

  1. 你真的需要UITableView吗?您可以使用UIScrollView,三个屏幕高。如果达到滚动结束,请布置内容并调整滚动位置。这给出了无限滚动的错觉。创建一些日期标签并在layoutSubviews:中安排它们不应该太费力。

  2. 如果你真的想坚持UITableView,你可以考虑拥有两个UITableViews。如果在第一个中滚动到达临界点,则旋转一个线程并填充第二个线程。然后在某些时候,交换视图并手动触发滚动,以便用户不记录更改。这只是我头脑中的一些想法。我还没有实现这样的东西,但我实现了无限的UIScrollView。

答案 3 :(得分:0)

我在另一篇文章中回答了这个问题:https://stackoverflow.com/a/15305937/2030823

包括:

https://github.com/samvermette/SVPullToRefresh

当UITableView到达底部时,SVPullToRefresh处理逻辑。自动显示微调器并触发回调块。您将业务逻辑添加到回调块中。

#import "UIScrollView+SVInfiniteScrolling.h"

// ...

[tableView addInfiniteScrollingWithActionHandler:^{
    // append data to data source, insert new cells at the end of table view
    // call [tableView.infiniteScrollingView stopAnimating] when done
}];

答案 4 :(得分:0)

此问题已被提出:implementing a cyclic UITableView 我正在复制这个答案,以便更容易,因为提问者没有勾选我的答案。

UITableView与scrollViewDidScroll方法中的UIScrollView相同。

因此,它很容易模仿无限滚动。

  1. 将数组加倍,使头部和尾部连接在一起,以模拟圆形表格

  2. 使用我的以下代码,当用户往往到达表的开头或结尾时,用户可以在doubled表的1st部分和doubled表的2nd部分之间切换。

  3. /* To emulate infinite scrolling...
    
    The table data was doubled to join the head and tail: (suppose table had 1,2,3,4)
    1 2 3 4|1 2 3 4 (actual data doubled)
    ---------------
    1 2 3 4 5 6 7 8 (visualizing joined table in eight parts)
    
    When the user scrolls backwards to 1/8th of the joined table, user is actually at the 1/4th of actual data, so we scroll instantly (we take user) to the 5/8th of the joined table where the cells are exactly the same.
    
    Similarly, when user scrolls to 6/8th of the table, we will scroll back to 2/8th where the cells are same. (I'm using 6/8th when 7/8th sound more logical because 6/8th is good for small tables.)
    
    In simple words, when user reaches 1/4th of the first half of table, we scroll to 1/4th of the second half, when he reaches 2/4th of the second half of table, we scroll to the 2/4 of first half. This is done simply by subtracting OR adding half the length of the new/joined table.
    
     Written and posted by Anup Kattel. Feel free to use this code. Please keep these comments if you don't mind.
    */
    
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView_ 
    {  
    
        CGFloat currentOffsetX = scrollView_.contentOffset.x;
        CGFloat currentOffSetY = scrollView_.contentOffset.y;
        CGFloat contentHeight = scrollView_.contentSize.height;
    
        if (currentOffSetY < (contentHeight / 8.0)) {
        scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY + (contentHeight/2)));
        }
       if (currentOffSetY > ((contentHeight * 6)/ 8.0)) {
           scrollView_.contentOffset = CGPointMake(currentOffsetX,(currentOffSetY - (contentHeight/2)));
        }
    
    }
    

    P.S。 - 我在我的一个名为NT Time Table(Lite)的应用程序中使用了这段代码。如果您想要预览,可以查看应用:https://itunes.apple.com/au/app/nt-time-table-lite/id528213278?mt=8

    如果您的表有时太短,在上述方法的开头,您可以添加一个if逻辑,以便在数据计数例如小于9时退出。