Animate Layout Changes inside UICollectionViewCell and it's subviews having AutoLayout constraints

822 views Asked by At

I'm increasing/decreasing the size of a collection view cell upon selection. The cell has subviews including a green bar, a the label "vs" and two numeric text fields. As shown on the gif/link below. The challenge is to animate the scale and also animate the subviews scale contained within the cell and maintain the layout constraints given. What is happening as shown on the video, is that the target layout jumps to it's final destination without animating the changes. On initial click, the cell "5vs0" scales nicely but the "0" textfield jumps to the far right without any animation. On second click to minimise the scale, the green bar on the left immediately resize to value equal to the textfields 5 and 0. This means that the auto layout constraints are working well with the container view (collection view cell) when it scales! The only problem is that the layout constraints do not animate along with the collection view's invalidate layout.

Video showing collection view cell scale but unintended subview jerky changes

I've set up the xib file with no auto layout warnings or errors. The collection view's layout get invalidated upon cell click, and a call to setCollectionViewLayout with animation set to true. NB after which I call a central dispatch to the main queue to call layoutIfNeeded against the collection view cell that needs changing. This doesn't seem to affect the layout animation on the subviews. Structure wise, as written on the code below, I keep a dictionary of layouts to which I toggle in between selecting a cell item.

I could manually invoke animation blocks to change the bounds of the subviews, however this is rather messy against different iOS screen sizes etc.

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
    var cell = collectionView.cellForItemAtIndexPath(indexPath) as! MatchEntryCell

    if (collectionView.collectionViewLayout.isEqual(self.layouts[.Standard]!)){
        collectionView.setCollectionViewLayout(self.layouts[.Edit]!, animated: true)
        cell.homeScore!.userInteractionEnabled = true
        cell.homeScore!.becomeFirstResponder()
        picker.selectRow(cell.homeScore!.text.toInt()! , inComponent: 0, animated: true)
        picker.selectRow(cell.awayScore!.text.toInt()! , inComponent: 1, animated: true)

    } else if (collectionView.collectionViewLayout.isEqual(self.layouts[.Edit]!)) {
        collectionView.setCollectionViewLayout(self.layouts[.Standard]!, animated: true)
        cell.homeScore!.resignFirstResponder()
        cell.homeScore!.userInteractionEnabled = false
    }
    dispatch_async(dispatch_get_main_queue()) {
        UIView.animateWithDuration(0.5, animations: { () -> Void in
            cell.layoutIfNeeded()
        })
    }
}

I've added autoresizing masks with width and height as well as below for the subviews on my UICollectionViewCell subclass. But no joy! This post is related to this solution, but I have no joy! Autolayout is not resizing Uicollectionviewcell items when animating between layouts

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.layer.borderWidth = 1
    self.layer.cornerRadius = 10
    self.layer.borderColor = UIColor.clearColor().CGColor

    self.homeBar?.autoresizingMask = .FlexibleWidth | .FlexibleHeight
    self.homeScore?.autoresizingMask = .FlexibleWidth | .FlexibleHeight
    self.awayBar?.autoresizingMask = .FlexibleWidth | .FlexibleHeight
    self.awayScore?.autoresizingMask = .FlexibleWidth | .FlexibleHeight
    self.autoresizingMask = .FlexibleWidth | .FlexibleHeight
}

Anyone have any ideas or suggestions? Cheers!

1

There are 1 answers

1
Edgardo Agno On

I've solved this problem by using legacy springs and struts. The alignment rects don't interpolate the collection view cell's itemSize change when using auto layout, but springs and struts does.