【问题标题】:Getting the current page获取当前页面
【发布时间】:2025-11-23 04:50:01
【问题描述】:

在我的滚动视图中,我想获取正在显示的当前页面(也许页面不是正确的术语)。我找不到任何包含这个的变量。但我认为它必须放在某个地方,因为指示器能够显示当前正在显示滚动视图的哪个子视图。

这是对我们完全隐藏还是有办法让我访问它?

【问题讨论】:

    标签: ios objective-c iphone cocoa-touch uiscrollview


    【解决方案1】:

    当前页面没有UIScrollView 属性。你可以计算它:

    int page = scrollView.contentOffset.x / scrollView.frame.size.width;
    

    如果要向上或向下舍入到最近的页面,请使用:

    CGFloat width = scrollView.frame.size.width;
    NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;
    

    【讨论】:

    • 用户滚动时不要忘记使用UIScrollViewDelegate获取当前页面!
    • 这在处理旋转时可能会出现问题。
    • 请添加 swift 版本
    • 这并不总是有效,有时框架宽度是错误的。
    • 这并不总是有效。有时我将页面显示为 0,这在我的情况下是错误的。
    【解决方案2】:

    我非常推荐你使用这个代码

    int indexOfPage = scrollView.contentOffset.x / scrollView.frame.size.width;
    

    但是如果您使用此代码,您的视图不需要完全位于 indexOfPage 为您提供的页面上。 这是因为我也建议您仅在此方法中使用此代码

    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{}
    

    当你的 scrollView 完成滚动并让你的页面数量非常清晰时调用它

    我建议您使用此代码将滚动视图设置为启用分页

    [scrollView setPagingEnabled:YES];
    

    所以最后应该是这样的

    -(void) methodWhereYouSetYourScrollView
    {
       //set scrollView
       [scrollView setPagingEnabled:YES];
       scrollView.delegate = self;
    }
    
    -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    {
       int indexOfPage = scrollView.contentOffset.x / scrollView.frame.size.width;
       //your stuff with index
    }
    

    【讨论】:

    • 无法在 iOS7 设备(使用 XCODE 6.2 编译)上运行 scrollViewDidEndDecelerating 时 contentOffset.x 等于 639 而不是 640(不要问我为什么...)。 user363349 的答案是正确的:return floor((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    • 这并不总是有效。有时我将页面显示为 0,这在我的情况下是错误的。
    【解决方案3】:

    我会在扩展中快速完成:

    extension UIScrollView {
        var currentPage:Int{
            return Int((self.contentOffset.x+(0.5*self.frame.size.width))/self.frame.width)+1
        }
    }
    

    然后只需调用:

    scrollView.currentPage
    

    【讨论】:

    • 几乎完美,我不得不删除最后的 +1,因为在我的世界里一切都是零
    【解决方案4】:

    同上,但作为一个类别

    
    @interface UIScrollView (CurrentPage)
    -(int) currentPage;
    @end
    @implementation UIScrollView (CurrentPage)
    -(int) currentPage{
        CGFloat pageWidth = self.frame.size.width;
        return floor((self.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    }
    @end
    

    【讨论】:

    • 这有点过头了,用 return round(self.contentOffset.x / self.frame.size.width);更简单,更容易理解..
    • -1 @LeonardPauli。上面的实现返回超过 50% 可见的页面。幼稚的实现仅在滚动视图的子视图占据整个滚动视图边界时更改页面值。
    • @user 首先, floor() 始终向下舍入,如果小数部分 >= 5,则 round() 向上舍入,否则向下舍入。话虽如此,地板(a)=圆形(a-0.5)。让我们做一些简单的代数。地板((ab/2)/b)+1 = 地板(a/b-0.5)+1 = 圆形(a/b-0.5-0.5)+1 = 圆形(a/b-1)+1 = 圆形( a/b)。看!看起来像 floor((a-b/2)/b)+1 = round(a/b)!数学。
    • 但是,如果我出于某种原因会使用 floor 来代替,那您就完全正确了! ;)
    【解决方案5】:

    另一种方式

    extension MyViewController: UIScrollViewDelegate {
        func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
            let width = scrollView.frame.width
            let page = Int(round(scrollView.contentOffset.x/width))
            print("CurrentPage:\(page)")
        }
    }
    

    【讨论】:

      【解决方案6】:

      这里已经有一些很好的答案。但是,对于内容不完全适合页面的情况 - 如果您像我一样想将结果用于UIPageControl,那么使用ceil 函数是必不可少的。

      让我们举个例子,我有“四页”的内容。

      我将基于我当前的现实生活示例。内容大小宽度为 3140 点。根据我的集合视图框架大小,页面宽度为 728。

      所以页数等于:

       3140 / 728 = 4.313 
      

      我的numberOfPages 将是五岁。其中四个将完整显示,最后一个 - 第 5 页 - 将显示剩余的 0.313 内容。

      现在,numberOfPages 为 5 意味着页面索引将为 0、1、2、3 和 4。

      当我向右滑动,向最终偏移量翻页时,scrollViewDidEndDecelerating 方法给出的最终 X 偏移量为 2412。

      应用舍入计算:

      2412 / 728 = 3.313 then rounded = 3
      

      这是不正确的。页面用户正在查看的偏移量应该是:

      Offset / Page User Is Viewing
      0        0
      728      1
      1456     2
      2184     3
      2412     4
      

      使用ceil的正确计算:

      private func pageForOffset(offset:CGFloat, pageWidth width:CGFloat) -> Int
      {
          let page = Int(ceil(offset / width))
          NSLog("\(__FUNCTION__) offset \(offset) width \(width) page \(page) ")
          return page
      }
      

      【讨论】:

        【解决方案7】:

        只需将当前偏移量除以页面大小即可:

        CGFloat pageNum = (int)(scrollView.contentOffset.x / scrollView.frame.size.width);
        

        【讨论】:

        • 转换为 int 然后分配给浮点数?为什么不将 pageNum 也设为 int ;)
        【解决方案8】:

        Aoakenfo 的解决方案很神奇,这是另一个结合你的代码和函数 scrollViewDidScroll 和 PageController 的解决方案

        - (void)scrollViewDidScroll:(UIScrollView *)sender {
            if (sender == self.scroll) {
                int pageNum = (int)(self.scrPage.contentOffset.x / self.scrPage.frame.size.width);
                self.pagecontroller.currentPage =pageNum;
            }
        }
        

        【讨论】:

        • 这是贪婪的,不是懒惰的……它也不是 MVC。一个更简单的方法是在滚动时使 currentPage 无效,并仅在请求时设置它...全部来自 UIScrollView 上的子类或类别
        【解决方案9】:

        为了快速,我会使用这个

            let width = scrollView.frame.width
            let page = round(scrollView.contentOffset.x/width)
        

        非常简单,它基本上取scrollview x 位置,除以scrollview 宽度,然后舍入。

        【讨论】:

          【解决方案10】:

          在 xCode 7.x swift 2.x 中你可以这样做:

          //MARK: - ScrollView Extensions
          // Get the current page number
          extension UIScrollView {
              var currentPage: Int {
                  return Int(round(self.contentOffset.x / self.bounds.size.width))
              }
          
          // If you have reversed offset (start from contentSize.width to 0)
              var reverseCurrentPage: Int {
                  return Int(round((contentSize.width - self.contentOffset.x) / self.bounds.size.width))-1
              }
          }
          

          【讨论】:

            【解决方案11】:

            我从我们的几个应用程序中提取了这个...

            - (NSInteger)currentPage
            {
                if (0 == self.frame.size.width) {
                    NSLog(@"frame width == 0!");
                    return 0;
                }
                if (! self.currentPageValid) {
                    _currentPage = round(self.contentOffset.x / self.frame.size.width);
                    self.currentPageValid = YES;
                }
                return _currentPage;
            }
            

            Full source here

            【讨论】:

              【解决方案12】:

              您使用的是 UIPageControl 吗?如果是这样,这有一个currentPage 属性。如果没有,我认为您需要根据 scrollView 偏移量计算页面索引。

              【讨论】:

                【解决方案13】:

                Swift 5.1+ UIScrollView 扩展(省略 return 关键字)

                extension UIScrollView {
                
                    var currentPage: Int {
                        Int(round(self.contentOffset.x / self.frame.width))
                    }
                }
                

                【讨论】:

                  【解决方案14】:

                  如果有人在 C# 中寻找 Xamarin 的方法

                      public int CurrentIndex
                      {
                          get => (int)Math.Round(this.scrollView.ContentOffset.X / this.scrollView.Frame.Width);
                          set => this.scrollView.ScrollRectToVisible(new CGRect(new CGPoint(this.scrollView.Frame.Size.Width * value, 0), this.scrollView.Frame.Size), true);
                      }
                  

                  这个 getter 和 Setter 应该为您提供当前页面以及让您滚动到指定页面

                  【讨论】: