Getting the screen location of a cell from a UICollectionView

前端 未结 6 1431
野性不改
野性不改 2021-01-30 10:20

This isn\'t so much a question as an explanation of how to solve this problem.

The first thing to realize is that the UICollectionView does inherit from a <

相关标签:
6条回答
  • 2021-01-30 10:54

    @Alivin solution using layoutAttributesForItemAtIndexPath works but only for the presented/current scroll view that the user sees.

    Meaning, if you select the first presented visible cells you will get the actual frame, but if you scroll, the frame will have a deviation and you won't get the coordinates you need.

    This is why you need to use convertPoint:toView :

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

    Basically this method takes a point (cell.center) in one view and convert that point to another view (collectionView.superview) coordinate system which is exactly what we need.

    Thus, realCenter will always contain the coordinates to the actual selected cell.

    0 讨论(0)
  • 2021-01-30 10:55

    I needed to know the exact location of the cell's center that a user tapped relative to the UIWindow. In my situation the collectionView was a child of a view that took up 2/3 of the screen and its superview was a child of another view. Long story short using the collectionView.superView wasn't suffice and I needed the window. I used Ohadman's answer above and this answer from TomerBu to get the tapped location of the screen/window's coordinate system.

    Assuming your app has 1 window that it isn't connected across multiple screens, I used both of these and the same exact location printed out.

    It's important to know that this is going to give you the exact middle of the cell (relative to the window). Even if you touch the top, left, bottom or right side of the cell it's going to return the coordinate of the center of the cell itself and not the exact location that you tapped.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
        guard let cell = collectionView.cellForItem(at: indexPath) as? YourCell else { return }
        guard let layoutAttributes = collectionView.layoutAttributesForItem(at: indexPath) else { return }
        guard let window = UIApplication.shared.keyWindow else { return }
    
        let touchedLocationInWindow = collectionView.convert(cell.center, to: window)
        print("OhadM's version: \(touchedLocationInWindow)")
    
        let cPoint = layoutAttributes.center
        let tappedLocationInWindow = collectionView.convert(cPoint, to: window)
        print("TomerBu's version: \(tappedLocationInWindow)")
    }
    
    0 讨论(0)
  • 2021-01-30 10:58

    An alternative is to use the events to provide most if not all the answers to your questions.

    I presume that a touch event will initiate all of this, so lets implement something meaningful;

      //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!!
    
    
      }
    }
    

    oh ... before you rush off for happy hour, lets not forget to read up on;

       <UICollectionViewDelegate> (hint - it's needed)  
    
    0 讨论(0)
  • 2021-01-30 11:09
    -(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);
    }
    

    It work for me.You can try yourself

    0 讨论(0)
  • 2021-01-30 11:14

    Well the first part of your question is pretty much clear, the second one?? anyway if what you want to get is the frame of the select cell in your collection you can use this :

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

    More info here

    0 讨论(0)
  • 2021-01-30 11:15

    I've done this before as well. it took a while but it is possible.

    You need to use

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

    Where currentImageView is the image that the user taps. It's superview will be the cell. You want to convert the rect of your image to where it actually is on a different view. That view is called "translateView" here.

    So what is translateView? In most cases it is just self.view.

    This will give you a new frame for your imageview that will meet where your image is on your table. Once you have that you can expand the image to take up the entire screen.

    Here is a gist of the code I use to tap an image then expand the image and display a new controller that allows panning of the image.

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

    0 讨论(0)
提交回复
热议问题