web-dev-qa-db-ja.com

iOS6 UICollectionViewおよびUIPageControl-表示セルを取得する方法は?

IOS6の新機能を研究中に ICollectionView について質問がありました。
現在、フローレイアウトでテストし、スクロール方向を水平に設定し、スクロールとページングを有効にします。サイズをカスタムのセルとまったく同じに設定したので、一度に1つずつ表示できます。横にスクロールすると、ユーザーには他の既存のセルが表示されます。

完璧に機能します。

次に、作成したコレクションビューに IPageControl を追加して、表示されているセルとそこにあるセルの数を表示できるようにします。

ページコントロールの構築はかなり単純で、frameとnumberOfPagesが定義されていました。

質問のタイトルにあるように、私が抱えている問題は、どのセルが現在コレクションビューに表示されているかを取得する方法です。そのため、ページコントロールのcurrentPageを変更できます。

CellForItemAtIndexPathなどのデリゲートメソッドを試しましたが、セルを表示するのではなくロードするために作成されています。 didEndDisplayingCellは、セルが表示されなくなったときにトリガーします。これは、必要なものの反対のイベントです。

コレクションビューメソッドである-visibleCellsおよび-indexPathsForVisibleItemsが正しい選択であるように見えますが、別の問題にぶつかりました。それらをいつトリガーするか?

事前に感謝します。皆さんが私を理解できるように、私が十分に明確にしたことを願っています!

36
gazzola

自分でUIScrollViewDelegateとして設定し、scrollViewDidEndDecelerating:methodのように:

Objective-C

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    CGFloat pageWidth = self.collectionView.frame.size.width;
    self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth;
}

スイフト

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

    let pageWidth = self.collectionView.frame.size.width
    pageControl.currentPage = Int(self.collectionView.contentOffset.x / pageWidth)
}
91
Sendoa

私もこれにしばらく苦労しましたが、UICollectionViewの親クラスをチェックアウトすることをお勧めしました。それらの1つはたまたま IScrollView であり、自分を IScrollViewDelegate として設定すると、scrollViewDidEndDeceleratingなどの非常に便利なメソッドにアクセスできます、UIPageControlを更新するのに最適な場所です。

18
Not Randy Marsh

スクロール位置ですぐにページ制御をより正確に更新するため、少し調整した計算と処理をお勧めします。

以下のソリューションは、任意のスクロールビューまたはそのサブクラス(UITableView UICollectionViewなど)で動作します

viewDidLoadメソッドでこれを書く

scrollView.delegate = self

次に、言語のコードを使用します。

スイフト3

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    {
       let pageWidth = scrollView.frame.width
       pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
    }

スイフト2:

func scrollViewDidScroll(scrollView: UIScrollView) 
{
   let pageWidth = CGRectGetWidth(scrollView.frame)
   pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}

客観的C

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat pageWidth = self.collectionView.frame.size.width;
    self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth;
}
17

コードが少ない別のオプションは、表示可能なアイテムインデックスパスを使用し、ページコントロールを設定することです。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row];
}
8
Ramesh
  1. ビューにPageControlを配置するか、コードで設定します。
  2. 設定IScrollViewDelegate
  3. Collectionview-> cellForItemAtIndexPath(メソッド)で、ページ数を計算するための以下のコードを追加します。

int pages = floor(ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];

ScrollView Delegateメソッドを追加し、

プラグママーク-UIPageControlのUIScrollVewDelegate

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    CGFloat pageWidth = ImageCollectionView.frame.size.width;
    float currentPage = ImageCollectionView.contentOffset.x / pageWidth;

    if (0.0f != fmodf(currentPage, 1.0f))
    {
        pageControl.currentPage = currentPage + 1;
    }
    else
    {
        pageControl.currentPage = currentPage;
    }
    NSLog(@"finishPage: %ld", (long)pageControl.currentPage);
}
5
Ramdhas

私はこれが古いものであることを知っていますが、この種の機能を再度実装する必要があり、より完全な答えを与えるために少し追加する必要があります。

まず:scrollViewDidEndDeceleratingの使用は、ユーザーがドラッグ中に指を持ち上げた(よりフリックアクションに近い)ため、減速フェーズがあることを前提としています。ユーザーが指を離さずにドラッグすると、UIPageControlはドラッグが開始される前の古いページを示します。代わりにscrollViewDidScrollコールバックを使用するということは、ドラッグとフリックの後、およびドラッグとスクロール中の両方でビューが更新されるため、ユーザーの応答性と正確さが大幅に向上します。

2番目に:選択されたインデックスの計算にpagewidthを使用する場合、すべてのセルの幅が同じであり、画面ごとに1つのセルがあると仮定します。 indexPathForItemAtPointUICollectionViewメソッドを利用すると、さまざまなレイアウトとセルサイズで機能する、より弾力性のある結果が得られます。以下の実装では、フレームの中心がpagecontrolで表される目的のセルであると想定しています。また、セル間スペースがある場合、スクロール中にselectedIndexがnilまたはオプションになる可能性があるため、pageControlで設定する前にこれをチェックしてアンラップする必要があります。

 func scrollViewDidScroll(scrollView: UIScrollView) {
   let contentOffset = scrollView.contentOffset
   let centrePoint =  CGPointMake(
    contentOffset.x + CGRectGetMidX(scrollView.frame),
    contentOffset.y + CGRectGetMidY(scrollView.frame)
   )
   if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){
     self.pageControl.currentPage = index.row
   }
 }

もう1つ-UIPageControlのページ数を次のように設定します。

  func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    self.pageControl.numberOfPages = 20
    return self.pageControl.numberOfPages
  } 
4
Dallas Johnson

シンプルなスイフト

public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)!
}

UIScrollViewDelegateを実装している場合、UICollectionViewDelegateはすでに実装されています

3
Michael