【问题标题】:How can I make uiscrollview infinite in iOS?如何在 iOS 中使 uiscrollview 无限?
【发布时间】:2013-10-16 14:25:33
【问题描述】:

我想这样滚动 1 2 3 1 2 3

我有一些按钮,假设是 10,我想在无限滚动中显示。

 numbercolors=[[NSMutableArray alloc] init];

 //total count of array is  49 

 numbercolors = [NSMutableArray arrayWithObjects:@"25",@"26",@"27",@"28",@"29",@"31",@"32",@"33",@"34",@"35", @"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23",@"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34",@"35", @"0",@"1",@"2",@"3",nil];

  int x=2500;

for (NSInteger index = 0; index < [numbercolors count]; index++)
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

    button.frame = CGRectMake(x ,0,29.0,77.0);

    button.tag = index;

    [button setTitle:[numbercolors objectAtIndex:index] forState:UIControlStateNormal];

    [button addTarget:self action:@selector(didTapButton:) 

    forControlEvents:UIControlEventTouchUpInside];

    [coloringScroll addSubview:button];

    x=x+70+29;
}
 [coloringScroll setContentSize:CGSizeMake(5000+ (29+70)*[numbercolors count], 1)];

 [coloringScroll setContentOffset:CGPointMake(2500+(29+70)*11, 0)];

这是我在滚动视图上制作按钮的代码。

如何在 - (void)scrollViewDidEndDecelerating:(UIScrollView *)sender 这个方法中设置无限滚动。

【问题讨论】:

标签: iphone objective-c ipad uiscrollview ios7


【解决方案1】:

主要思想是将您的滚动视图重新定位回某个恒定值,当它滚动到某个值时,然后正确地自动重新定位您的“1”、“2”、“3”项。

例如 - 您将拥有 contentwidth 5000 的滚动视图。默认情况下,您将其设置为位置 2500。

然后您只需签入- (void)scrollViewDidCScroll:(UIScrollView *)scrollview - 如果 scrollview.contentoffset.x > 3500 - 然后将其位置降低到 scrollview.contentoffset.x -=1000;

另一面也是如此。这将导致无限滚动。

但内容不会随之而来。所以 - 您需要实施额外的内容偏移值检查以正确重新排序和重新定位“1”、“2”、“3”、项目。

我通常使用 3 个元素,然后为它们动态预加载必要的图库图片。

如果您不想重新发明“轮子”,请查看以下解决方案:

https://www.cocoacontrols.com/controls/dmcircularscrollview

https://www.cocoacontrols.com/controls/infinitescrollview

https://www.cocoacontrols.com/controls/iainfinitegridview

【讨论】:

  • 我认为我有这个问题,因为我使用的是小图像,不知道如何设置 contentoffset。正因为如此,我把所有代码都放在这里.....
  • 对不起,但我知道我需要设置 contentoffset,重点是如何?
  • scrollview 内容偏移量可以这样改变:[scrollview setContentOffset:CGPointMake(2500, 0)];
  • 实际上我的对象(在数组中)不是固定的(第一次显示多少,铰孔多少)所以为此我如何为我的下一个视图设置 contentoffset。如果我有图像如果宽度为 320,那么我将 contentoffset 增加 320 的倍数,但在这里我不能。
  • 只需查看给出的示例 - 这样会更容易 + 您将看到代码并了解它是如何完成的。
【解决方案2】:

只需要设置 setContentOffset 计数

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.contentOffset.x > 2500+(29+70)*4 + ((29+70)*36)) {
        [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x-((29+70)*36),  0)];  
    }
    if (scrollView.contentOffset.x < 2500+(29+70)*4){
       [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x+((29+70)*36), 0)];
    }
}

【讨论】:

  • 为什么是 29、70、36?这些只是您选择的随机数还是有一些方法?
  • dat sa way 2 do it :)
  • 我们得到了一个可能的有效答案,现在我们中的一些人将不得不花费无限的时间来猜测这些数字是什么......))。至少给我们一些线索... ????????????
【解决方案3】:

您可以查看这个基于 Apple StreetScroller iOS 示例代码的解决方案:

https://github.com/gblancogarcia/GBInfiniteScrollView

希望对你有帮助!

【讨论】:

    【解决方案4】:

    我写了一个无限滚动的 UIscrollView 子类来完成这个任务。它基于 Apple StreetScroller 示例。您只需为其提供按钮标题以及是否需要水平滚动或垂直滚动​​。您还可以设置许多其他选项。它与我的 github 上的文档和示例项目一起发布。这是链接...

    http://github.com/ninefifteen/SSRollingButtonScrollView

    【讨论】:

      【解决方案5】:

      我已经在 swift 中实现了一个无限滚动。
      它的灵感来自苹果StreetScroller 示例

      我知道还不完美,但我认为是一个上帝的起点。

      InfiniteVerticalScroller

      【讨论】:

        【解决方案6】:

        这是一个老问题,但我写这篇文章是为了帮助寻找相同解决方案的人。假设我们想无限循环3个项目(cells) - C0, C1, C2,我们可以在中心cells的左右两侧生成dummy cell,结果如下,

        C0 C1 C2 [C0 C1 C2] C0 C1 C2

        括号中的单元格是我们通过设备屏幕看到的单元格,如果我们向左滚动,

        C0 [C1 C2 C0] C1 C2 C0 C1 C2

        此时,强制 contentOffset 指向给定虚拟单元格的右侧,

        C0 [C1 C2 C0] C1 C2 C0 C1 C2 -> C0 C1 C2 C0 [C1 C2 C0] C1 C2

        由于无缝地实现这一点很耗时,我推荐下面的解决方案。

        https://github.com/DragonCherry/HFSwipeView

        如果您只是想看看它是如何工作的,请点击下面的链接并“点击播放”。

        https://www.cocoacontrols.com/controls/hfswipeview

        【讨论】:

          【解决方案7】:

          对于右无限滚动,您可以使用 -

                  let rightOffset = CGPoint.init(x: (scrollView.contentSize.width) - (scrollView.bounds.width), y: 0)
              UIView.animate(withDuration: 3.0,
                             delay: 0.0,
                             options: [.curveLinear, .repeat],
                             animations: { () -> Void in
                              self.scrollView.contentOffset = rightOffset
          
              }, completion: { (finished: Bool) -> Void in
                  self.scrollView.setContentOffset(.init(x: 0, y: self.scrollView.contentOffset.y), animated: false)
              })
          

          【讨论】:

            【解决方案8】:

            这里提供的答案很好,但如果您仍然不满意并寻找不同的方法,这就是我所做的。

            主要思想是每当您到达最后一个单元格之前的单元格时更新单元格的数量。每次将项目数增加 1 时,都会产生无限滚动的错觉。为此,我们可以利用scrollViewDidEndDecelerating(_ scrollView: UIScrollView) 函数检测用户何时完成滚动,然后更新集合视图中的项目数。这是实现此目的的代码 sn-p:

            class InfiniteCarouselView: UICollectionView {
            
                var data: [Any] = []
            
                private var currentIndex: Int?
                private var currentMaxItemsCount: Int = 0
                // Set up data source and delegate
            }
            
            extension InfiniteCarouselView: UICollectionViewDataSource {
                func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                    // Set the current maximum to a number above the maximum count by 1
                    currentMaxItemsCount = max(((currentIndex ?? 0) + 1), data.count) + 1
                    return currentMaxItemsCount
            
                }
            
                func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
                    let row = indexPath.row % data.count
                    let item = data[row]
                    // Setup cell
                    return cell
                }
            }
            
            extension InfiniteCarouselView: UICollectionViewDelegateFlowLayout {
                func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
                    return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
                }
            
                // Detect when the collection view has finished scrolling to increase the number of items in the collection view
                func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
                    // Get the current index. Note that the current index calculation will keep changing because the collection view is expanding its content size based on the number of items (currentMaxItemsCount)
                    currentIndex = Int(scrollView.contentOffset.x/scrollView.contentSize.width * CGFloat(currentMaxItemsCount))
                    // Reload the collection view to get the new number of items
                    reloadData()
                }
            }
            

            优点

            • 直接实施
            • 不使用 Int.max(我个人认为这不是一个好主意)
            • 不使用任意数字(如 50 或其他)
            • 不更改或操纵数据
            • 没有手动更新内容偏移或任何其他滚动视图属性

            缺点

            • 应该启用分页(尽管可以更新逻辑以支持不分页)
            • 需要维护一些属性的引用(当前索引、当前最大计数)
            • 需要在每个滚动端重新加载集合视图(如果可见单元格很少,则没什么大不了的)。如果您在没有缓存的情况下异步加载某些内容,这可能会严重影响您(这是一种不好的做法,数据应该缓存在单元格之外)
            • 如果你想在两个方向上无限滚动就不行了

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-12-23
              • 2012-06-09
              • 1970-01-01
              相关资源
              最近更新 更多