現在のページを取得する


97

スクロールビューで、表示されている現在のページを取得したいと思います(ページが正しい用語ではない可能性があります)。これを保持する変数が見つかりません。しかし、インジケーターはスクロールビューのどのサブビューが現在表示されているかを示すことができるので、どこかで保持されている必要があると思います。

これは完全に私たちから隠されていますか、それとも私がそれにアクセスする方法はありますか?

回答:


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

これは、ローテーションを処理するときに問題が発生する可能性があります。
Jason McCreary 2013年

迅速なバージョンを追加してください
fnc12 '25

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
}

scrollViewDidEndDecelerating時のiOS7デバイス(XCODE 6.2でコンパイル)で機能しないcontentOffset.xは、640(理由は聞かないでください)ではなく639です。user363349正解:return floor((self.contentOffset.x-pageWidth / 2)/ pageWidth)+ 1;
ワシリー、2015

これは常に機能するとは限りません。時々私は私のページでは間違っている0としてページを取得しています。
Sneha

30

迅速に私は拡張してそれを行います:

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

次に呼び出すだけです:

scrollView.currentPage

10
すべてが私の世界でゼロに基づいているので、ほぼ完璧な、私は最後に+1を削除する必要がありました
mvandillen

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()が切り上げ、それ以外の場合は切り捨てます。つまり、floor(a)= round(a-0.5)です。簡単な代数を作ってみましょう。floor((ab / 2)/ b)+1 = floor(a / b-0.5)+1 = round(a / b-0.5-0.5)+1 = round(a / b-1)+1 = round( a / b)。ほら!フロア((ab / 2)/ b)+1 =ラウンド(a / b)のようです!数学。
Leonard Pauli 14年

しかし、ええ、もし私が何らかの理由で代わりに床を使用したとしたら、あなたは完全に正しかったでしょう!;)
Leonard Pauli

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も作成しないのですか;)
Klaas

6

ここにはすでに良い答えがいくつかあります。ただし、コンテンツがページにぴったり収まらないシナリオの場合-そして、私のように結果をに使用したいUIPageControl場合は、ceil関数です。

「4ビット」ページのコンテンツがある例を見てみましょう。

これは、現在の実際の例に基づいています。コンテンツサイズの幅は3140ポイントです。コレクションビューのフレームサイズに基づくと、ページ幅は728です。

したがって、ページ数は次のようになります。

 3140 / 728 = 4.313 

numberOfPagesは5歳になります。4つは全体が表示され、最後の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)

かなり単純ですが、基本的にはスクロールビューのx位置を取得し、それをスクロールビューの幅で除算してから丸めます。


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

このゲッターとセッターは現在のページを提供し、指定したページにスクロールできるようにする必要があります


0

Swift 5.1以降のUIScrollView拡張機能(returnキーワードを省略)

extension UIScrollView {

    var currentPage: Int {
        Int(round(self.contentOffset.x / self.frame.width))
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.