2009-09-29 74 views
20

所以,UITableView基本上支持“无限”滚动。有可能是一个限制,但吸盘可以滚动looonnnggg时间。我想用UIScrollView模仿这种行为,但有两个基本障碍:UIScrollView。任何想法实现“无限”滚动/缩放?

1)scrollView.contentSize在创建时已修复。 2)缩放可以将任何延迟加载方案全部拖到地狱,因为它可能导致infinte数据爆炸。

让别人思考这个主意吗?是的,我知道,我们本质上是在讨论在这里重新创建Google地图。任何见解将不胜感激。

干杯, 道格

+0

你看过MapKit吗? – 2009-09-29 18:10:43

+0

以及UITableView是UIScrollView的一个子类 – 2010-06-01 19:03:10

回答

10

虽然不可能有一个真正无限的UIScrollView,有一个你可以用它来模拟这种行为的一些简单的技巧。

  1. 处理固定contentSize:有你的滚动视图处理一些固定大小的视图,并在发射或实例,设置内容偏移,这样你所看到的处理视图的中间。然后只需观察内容偏移(使用KVO或其他方法),并且如果您靠近任何边缘,请使用新的内容集合(适当偏移)更新视图的内容,并将滚动视图的contentOffset属性重置为返回中间。
  2. 处理缩放:做类似的事情,只有这次在滚动视图上观看缩放因子。每当它到达某个特定点时,对所呈现的任何数据进行一些操作,以使其显示为缩放,然后将缩放因数重置为1.0。例如,如果您正在滚动图像并将其缩放为两倍,则以编程方式应用某种转换以使图像的大小增加两倍,然后将滚动视图的缩放因子重置为1.0。图像仍然会放大,但滚动视图将能够根据需要继续放大。 (谷歌地图借此一步在那里懒加载的用户更详细视图缩放 - 你可能会或可能不会选择来实现这一点。)
+2

下面是一个链接http://iphonedevelopment.blogspot.com/2009/02/kvo-and-iphone-sdk.html为任何不知道这是什么的人解释KVO。就像我没有。 – Grumdrig 2010-04-05 20:50:52

+4

这个解决方案的问题在于'setContentOffset'取消了正在发生的任何滚动和突然停止的动作。我不知道如何确定视图正在移动的速度,或者如果我确实如何重新开始该动作。 – Grumdrig 2010-04-05 21:19:59

+0

但为什么麻烦改变内容偏移呢?让它滚动,只要确保你保持并移动图像视图以符合用户的看法。 – 2010-09-22 15:23:32

0

也许设置contentSize一些巨大的价值,然后移动有限跟踪平铺样本中的视图位置的底层视图的数量会起作用。

为了缓解最终到达边缘并且不得不突然重新接收视图(取消当前正在运动的任何滚动)的可能性,视图可以在静止时不时重新接近。

无论如何,这就是我即将尝试的。

+0

这似乎工作正常,FYI。我使用了与包含视图一样大小的4个包含视图,这些视图与滚动一起前进。我将我的代码基于(上半部分)滚动样本。 – Grumdrig 2010-04-05 22:42:33

+0

Apple官方无限滚动示例项目建议使用此方法。 – zakdances 2013-03-22 06:11:34

13

我刚刚完成了为我实施的infitine卷轴。 在我的实现中,我有一个scrollView和Navigationbuttons的UITableViewCell。 scrollView包含全部具有相同宽度的x视图。视图水平排列并启用分页。

scrollView.clipsToBounds = YES; 
scrollView.scrollEnabled = YES; 
scrollView.pagingEnabled = YES; 
scrollView.showsHorizontalScrollIndicator = NO; 

我codelogic是这样的:

  1. 在我的初始化函数我
    • 创建所有视图(滚动视图)和
    • 把它们放到一个数组和
    • 将它们添加到scrollView
  2. 然后我调用一个函数,在循环中计算每个视图的位置(每次检测到滚动时,都需要调用该函数)。它始终占用数组的第一个元素,并将帧设置为(0,0,...,...),第二个元素设置为(i * width,0,....,....)等等上。 beeing调用的函数如下:

    - (void)updateOffsetsOfViews{ 
        int xpos = 0; 
        for (int i=0; i<[views count]; i++) { 
         UIImageView *_view = [views objectAtIndex:i]; 
         CGRect aFrame = _view.frame; 
         aFrame.origin.x = xpos; 
         aFrame.origin.y = 0.0; 
         _view.frame = aFrame; 
         xpos += viewWidth; 
        } 
        float center = 0; 
        if(fmod([views count],2) == 1){ 
         center = viewWidth * ([views count]-1)/2; 
        }else { 
         center = viewWidth * [views count]/2; 
        } 
        [scrollView setContentOffset:CGPointMake(center, 0)]; 
        lastOffset = center; 
    } 
    
  3. 然后(仍处于初始化过程中)我想补充一个观察者

    [scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:nil]; 
    

    所以每次的东西在滚动视图的变化,我得到了(observeValueForKeyPath) - 函数调用,就像这样:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
    { 
        UIImageView *_viewFirst = (UIImageView *)[views objectAtIndex:0]; 
        if (fmod([scrollView contentOffset].x,viewWidth) == 0.0) { 
         if ([scrollView contentOffset].x > lastOffset) { 
          [views removeObjectAtIndex:0]; 
          [views addObject:_viewFirst];     
          [self updateOffsetsOfViews];  
         }else if ([scrollView contentOffset].x < lastOffset) { 
          UIImageView *_viewLast = (UIImageView *)[views lastObject]; 
          [views removeLastObject]; 
          [views insertObject:_viewLast atIndex:0];    
          [self updateOffsetsOfViews]; 
         } 
        } 
    } 
    
  4. 而在的dealloc或viewDidUnload(取决于你如何实现它),不要忘了圣雷莫观察员。

    [scrollView removeObserver:self forKeyPath:@"contentOffset"]; 
    

希望这会有所帮助,您可能会注意到一些开销,但在我执行我也支持像滚动5页(嗯......无限)在一次和autoanimated滚动等,所以你可能会看到一些那可能会被扔掉。

+1

相当好的解决方案,但不要做使用==的浮点比较,它会中断。 – 2012-07-25 11:32:36

+0

我试过你的代码。但是当我快速滚动2页时,代码将无法正确处理。 – jeswang 2012-08-22 10:16:51

2

请注意,当滚动动画时,contentOffset会多次更改,而不仅仅是逐页,而是动画中的每一步。