CaptainCOOLGUY
CaptainCOOLGUY

Reputation: 1161

How to get location of UIView in modally presented viewController

I am presenting a viewcontroller with a custom presentationStyle. The parent Controller is a UICollectionViewController. In my didSelectAtIndexPath method of the UICollectionViewController I am taking the UIImageView of the selected cell and animating it to the location of a UIView's frame within the viewcontroller that is modally presented.

How can I get the UIView's frame of the modally presented viewcontroller?

self.imageView!.frame = trophyOverlayVC.trophyImageLocationView!.frame  

does not work.

It appears off the screen in most cases.

import UIKit

class CollectionHolderViewController: MainPageContentViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    [..insert other methods here..]

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath) as TrophyCollectionViewCell

        self.collectionViewController.collectionView!.scrollEnabled = false // disable scrolling so view won't move
        self.collectionViewController.collectionView!.userInteractionEnabled = false
        let innerOffset = collectionView.contentOffset as CGPoint // offset of content view due to scrolling
        let attributes = self.collectionViewController.collectionView!.layoutAttributesForItemAtIndexPath(indexPath) as UICollectionViewLayoutAttributes!
        let cellRect = attributes.frame // frame of cell in contentView

        imageView = UIImageView(frame: CGRectMake(cellRect.origin.x, cellRect.origin.y, cellRect.size.width, cellRect.size.height)) //places image in location of collectionViewCell.
        imageView!.image = UIImage(named: placeHolderArray[indexPath.row]) //change.
        imageView!.contentMode = UIViewContentMode.ScaleAspectFit

        self.collectionViewController.collectionView!.addSubview(imageView!)


        self.placeHolderArray[indexPath.row] = ""
        UIView.setAnimationsEnabled(false)
        self.collectionViewController.collectionView!.reloadItemsAtIndexPaths([indexPath])
        UIView.setAnimationsEnabled(true)

        var trophyOverlayVC = self.collectionViewController.storyboard!.instantiateViewControllerWithIdentifier("TrophyOverlayVC") as TrophyOverlayViewController
        trophyOverlayVC.modalPresentationStyle = UIModalPresentationStyle.Custom
        self.presentViewController(trophyOverlayVC, animated: false, completion: self.presentViewController(trophyOverlayVC, animated: false, completion: { (value: Void) in UIView.animateWithDuration(0.5, animations: {
        self.imageView!.frame = trophyOverlayVC.trophyImageLocationView!.frame
        }, completion: {
            (value: Bool) in
    }) })
}

Upvotes: 0

Views: 176

Answers (1)

Aaron Brager
Aaron Brager

Reputation: 66234

Instead of trying to animate it immediately, do this inside the presentViewController completion block (where you're currently passing nil). At this point, all of the frames will be set properly.

Also, this approach will only work if their superviews are placed identically in the coordinate system. Remember that a frame's origin (and a view's center) are coordinates in relation to their superview. If they're not the same, you'll need to use UIView's convertRect(_:toView:) or convertRect(_:fromView:) to convert the rect to the appropriate view's coordinate system.

Upvotes: 1

Related Questions