获取当前页面


97

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

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

Answers:


263

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;

7
UIScrollViewDelegate当用户滚动时,请不要忘记使用来获取当前页面!
Sam Spencer

处理旋转时可能会有问题。
杰森·麦克雷里

请添加快速版本
fnc12

1
这并非总是可行,有时边框宽度不正确。
罗德里戈·鲁伊斯

这并不总是有效。有时我将页面设为0,这对我来说是错误的。
Sneha

32

我非常推荐您使用此代码

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

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

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

当您的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;
瓦西里(Vassily)

这并不总是有效。有时我将页面设为0,这对我来说是错误的。
Sneha


12

同上,但作为一个类别


@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

6
太过分了,只需要使用return round(self.contentOffset.x / self.frame.size.width); 更简单,更容易理解..
伦纳德圣保利

-1 @LeonardPauli。上面的实现返回的页面可见度超过50%。天真的实现仅在滚动视图的子视图占据整个滚动视图边界时才更改页面值。
用户

1
@user首先,floor()总是四舍五入,如果小数部分> = 5,则round()会四舍五入,否则是四舍五入。话虽如此,地板(a)=圆形(a-0.5)。让我们做一些简单的代数。floor((ab / 2)/ b)+1 =地板(a / b-0.5)+1 =圆形(a / b-0.5-0.5)+1 =圆形(a / b-1)+1 =圆形( a / b)。看!好像floor((ab / 2)/ b)+1 = round(a / b)!数学的。
伦纳德·保利

但是,是的,如果由于某种原因我会改用地板,那您将完全正确!;)
Leonard Pauli 2014年

8

另一种方式

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

6

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

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

11
转换为int,然后分配给float?为什么不将pageNum int也设为;)
克拉斯

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
}

4

为了快速我只会用这个

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

非常简单,基本上是将scrollview x位置除以scrollview宽度,然后将其四舍五入。


3

在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
    }
}

3

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

1
这是贪婪的,不是懒惰的。它也不是MVC。一种更简单的方法是使滚动上的currentPage无效,并仅在需要时进行设置...全部来自UIScrollView的子类或类别

2

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

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

完整资料在这里


1

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


0

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

    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应该会为您提供当前页面,并让您滚动到指定页面


0

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

extension UIScrollView {

    var currentPage: Int {
        Int(round(self.contentOffset.x / self.frame.width))
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.