web-dev-qa-db-ja.com

UICollectionViewからセルの画面位置を取得する

これは、この問題を解決する方法の説明としての質問ではありません。

最初に実現することは、UICollectionViewUIScrollViewから継承することです。したがって、スクロールビューのコンテンツを使用して標準のルックアップを行うことが最善の解決策です。

私が対処していた問題は次のとおりです。

異なる種類のセルとともに、各セルに異なるアイテムがあるUICollectionViewがありました。セル内の画像の効果を拡大して画面全体を引き継ぐようにするには、セルを選択する必要があります。私がどのように拡張を行ったかは、別の投稿のためです。

課題は、画面上のセルの位置を取得して、アニメーションセクションが開始点からの参照ポイントを持つようにすることでした。

したがって、この情報の取得を容易にするために、次のコードを検討してください。

最初のメモ:

UICollectionView *picturesCollectionView;
DrawingCell cell; // -> instanceof UICollectionViewCell with custom items.

// first, get the list of cells that are visible on the screen - you must do this every time
// since the items can change...  This is a CRITICAL fact.  You do not go through the
// entire list of cells - only those the collectionView indicates are visible.  Note 
// there are some things to watch out for - the visibles array does not match the indexPath.item
// number - they are independent.  The latter is the item number overall the cells, while
// the visibles array may have only 2 entries - so there is NOT a 1-to-1 mapping - keep
// that in mind.

NSArray *visibles = [self.picturesCollectionView visibleCells];

// now, cycle through the times and find the one that matches some criteria.  In my
// case, check that the cell for the indexPath passed matches the cell's imageView...
// The indexPath was passed in for the method call - note that the indexPath will point
// to the number in your datasource for the particular item - this is crucial.

for (int i=0; i<visibles.count; i++) {
    DrawingCell *cell = (DrawingCell *)visibles[i];
    if (cell.imageView.image == (UIImage *)images[indexPath.item]) {

        // at this point, we've found the correct cell - now do the translation to determine
        // what is it's location on the current screen...  You do this by getting the contentOffset
        // from the collectionView subtracted from the cell's Origin - and adding in (in my case)
        // the frame offset for the position of the item I wish to animate (in my case the
        // imageView contained within my custom collection cell...

        CGFloat relativeX = cell.frame.Origin.x - self.picturesCollectionView.contentOffset.x + cell.imageView.frame.Origin.x;
        CGFloat relativeY = cell.frame.Origin.y - self.picturesCollectionView.contentOffset.y + cell.imageView.frame.Origin.y;

        // I now have the exact screen coordinates of the imageView - so since I need this
        // to perform animations, I save it off in a CGRect - in my case, I set the size
        // exactly to the size of the imageView - so say you were doing a Flicker display
        // where you wanted to grow a selected image, you get the coordinates of the image
        // in the cell and the size from the displayed image...

        UIImageView *image = cell.imageView;

        // selectedCell is a CGRect that's global for the sake of this code...

        selectedCell = cell.frame;
        selectedCell.Origin.x = relativeX;
        selectedCell.Origin.y = relativeY;
        selectedCell.size.width = cell.imageView.frame.size.width;
        selectedCell.size.height = cell.imageView.frame.size.height;
    }
}

// done.  I have my coordinates and the size of the imageView I wish to animate and grow...

うまくいけば、これはセルに何かを正確な位置に重ねるなどの言い方を見つけようとしている他の人々を助けます...

47
Joe Jupin
-(void)collectionView:(UICollectionView *)cv didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
{

UICollectionViewLayoutAttributes *attributes = [cv layoutAttributesForItemAtIndexPath:indexPath];

CGRect cellRect = attributes.frame;

CGRect cellFrameInSuperview = [cv convertRect:cellRect toView:[cv superview]];

NSLog(@"%f",cellFrameInSuperview.Origin.x);
}

それは私のために働いています。あなたは自分で試すことができます

74
Alivin

さて、あなたの質問の最初の部分はかなり明確です、2番目の部分は??とにかくあなたが取得したいものがコレクションの選択セルのフレームである場合、これを使用できます:

UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];
CGRect cellRect = attributes.frame;

詳細 こちら

41
elio.d

layoutAttributesForItemAtIndexPathを使用した@Alivinソリューションは機能しますが、ユーザーに表示される表示/現在のスクロールビューに対してのみ有効です。

つまり、first表示されている表示セルを選択すると、実際のframeが表示されます。butスクロールするとframeが表示されます偏差があり、必要な座標を取得できません。

これがconvertPoint:toViewを使用する必要がある理由です:

let realCenter = collectionView.convertPoint(cell.center, toView: collectionView.superview)

基本的に、このメソッドは1つのビューでポイント(cell.center)を取得し、そのポイントを別のビュー(collectionView.superview)座標系に変換します。これはまさに必要なものです。

したがって、realCenterには、実際に選択されたセルの座標が常に含まれます。

17
OhadM

私も前にこれをやったことがあります。しばらくかかりましたが、可能です。

使用する必要があります

[currentImageView.superview convertRect:currentImageView.frame toView:translateView]

CurrentImageViewは、ユーザーがタップする画像です。スーパービューはセルになります。画像の四角形を、実際に別のビュー上にある場所に変換したい場合。このビューは、ここでは「translateView」と呼ばれます。

それでは、translateViewとは何ですか?ほとんどの場合、それはただself.view

これにより、テーブル上の画像の場所に合わせて、imageviewの新しいフレームが提供されます。それができたら、画面全体を占めるように画像を拡大できます。

以下は、画像をタップしてから画像を展開し、画像をパンできる新しいコントローラーを表示するために使用するコードの要点です。

https://Gist.github.com/farhanpatel/4964372

7
Farhan Patel

別の方法としては、イベントを使用して、質問に対するすべてではないにしてもほとんどの回答を提供することです。

タッチイベントがこれらすべてを開始すると想定しているため、意味のある何かを実装しましょう。

  //First, trap the event in the collectionView controller with;

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

   // lets ensure it's actually visible (yes we got here from a touch event so it must be... just more info)
   if ([self.collectionView.indexPathsForVisibleItems containsObject:indexPath]) {

     // get a ref to the UICollectionViewCell at indexPath
     UICollectionViewCell *cell =(UICollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];

     //finally get the rect for the cell
     CGRect cellRect = cell.frame


      // do your processing here... a ref to the cell will allow you to drill down to the image without the headache!!


  }
}

ああ...ハッピーアワーのために急いで行く前に、読み進めることを忘れないでください。

   <UICollectionViewDelegate> (hint - it's needed)  
1
mdb983