37

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

それは完全に機能します。

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

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

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

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

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

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

4

8 に答える 8

18

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

于 2012-11-10T04:14:51.743 に答える
17

少し調整された計算と処理をお勧めします。これにより、どのスクロール位置でもページ コントロールがすぐに更新され、精度が向上します。

以下のソリューションは、任意のスクロール ビューまたはそのサブクラス (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;
}
于 2014-05-08T13:08:30.300 に答える
8

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

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

int ページ = フロア (ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:ページ];

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);
}
于 2015-01-05T06:38:01.073 に答える
4

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

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

第 2に、選択したインデックスを計算するために に依存することはpagewidth、すべてのセルが同じ幅であり、画面ごとに 1 つのセルがあることを前提としています。indexPathForItemAtPoint上のメソッドを利用するとUICollectionView、さまざまなレイアウトやセル サイズで機能する、より回復力のある結果が得られます。以下の実装では、フレームの中心が で表される目的のセルであると想定してい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
  } 
于 2016-02-06T14:54:09.917 に答える
3

シンプルなスイフト

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

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

于 2015-10-06T14:30:03.780 に答える