3

I am trying to make a transition animation like the demonstration in the link here. So when I clicked the cell, it expands and covers the whole screen.

Here are my codes(I have to admit that I am not familiar with CollectionView)`

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

@IBOutlet weak var mainDesLabel: UILabel!
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var secDesLabel: UILabel!
let searchBar = UISearchBar()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.collectionView.delegate   = self
    self.collectionView.dataSource = self
    self.collectionView.backgroundColor = UIColor.clearColor()
    ////////////////////////////////////////////////////////////////////////
    self.searchBar.frame = CGRect(x: 175, y: 0, width: 200, height: 50)
    self.searchBar.searchBarStyle = UISearchBarStyle.Minimal
    self.searchBar.backgroundColor = UIColor.whiteColor()
    self.view.addSubview(searchBar)
    ////////////////////////////////////////////////////////////////////////
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as UICollectionViewCell

    cell.layer.cornerRadius = 5

    return cell
}



func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

//Use for size
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    self.collectionView.frame = self.view.bounds
    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    cell!.frame = CGRectMake(0, 0, self.view.bounds.width, self.view.bounds.height)
}


}

So I thought use 'didSelectItemAtIndexPath' would help, however it turns out like this

thoughts? Any help would be highly appreciated!

Rohit Khandelwal
  • 1,778
  • 15
  • 23
Di Wang
  • 31
  • 1
  • 8
  • https://www.raywenderlich.com/113845/ios-animation-tutorial-custom-view-controller-presentation-transitions – HMHero Jun 30 '16 at 07:45

4 Answers4

4

Or what you can do is expand the item and change its frame with UIAnimation.

And when he cell is tapped, you get the views inside the cell to be expanded also using auto layout and I'm hinting towards (clips to bounds).

something like this:

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let item = collectionView.cellForItemAtIndexPath(indexPath) as! cellCollectionViewExpress  // or whatever you collection view cell class name is.

    UIView.animateWithDuration(1.0, animations: {
        self.view.bringSubviewToFront(collectionView)
        collectionView.bringSubviewToFront(item)
        item.frame.origin = self.view.frame.origin   /// this view origin will be at the top of the scroll content, you'll have to figure this out
        item.frame.size.width = self.view.frame.width
        item.frame.size.height = self.view.frame.height
    })
}

I would suggest you that you use UICollectionView Controller, so things are at ease in general with using that.

Akshansh Thakur
  • 5,163
  • 2
  • 21
  • 38
3

You cannot just use didSelectItemAtIndexPath or any similar methods to update the size of a UICollectionViewCell once the UICollectionView is done performing the view layout.

To update cell height, You can first capture which cell had been tapped in didSelectItemAtIndexPath. Then, you can either reload the entire collection view with the new cell frame being passed in the sizeForItemAtIndexpath. Or, you can just reload the specific cell with reloadItemsAtIndexPaths, but you still need to pass the updated size of the cell via sizeForItemAtIndexpath.

UPDATE I now see the question details have been updated by an animation which you desire to have.

I had performed a similar animation by:-

  1. Capturing the cell which had been tapped in didSelectItemAtIndexPath.
  2. Adding a replica view to the UIViewContrller, but with its frame totally coinciding with the cell which had been tapped.
  3. Then, animating this view which had been added. Thus giving an impression that the cell was animated.

Any additional functionality which has to be given can also be written in this view. Thus the code of the cell and the animated view is separated too.

7vikram7
  • 2,764
  • 1
  • 25
  • 43
  • Thx, it does give me a thought of how to achieve this. Do you have an example for that? I am confused with some steps. – Di Wang Jun 30 '16 at 07:26
  • For example, I try to put a uiview which coincidely covers the cell however it was added to the cell… – Di Wang Jun 30 '16 at 09:11
  • UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath]; Then, with attributes.frame you can get frame of cell. Now you need to place the replica view on the note viewcontroller using this frame. (Note: viewcontroller, not cell or collectionview) – 7vikram7 Jun 30 '16 at 09:37
  • Your suggestion basically works. However, the cell just pops up from the button of the view controller instead of growing from the cell itself...https://github.com/Imsiaocong/DribbleExp I post it on my github, would you check it out and see what is wrong? – Di Wang Jul 01 '16 at 06:45
  • Just checked your code. Instead of simple using "animateWithDuration:animations"; use "animateWithDuration:delay:options:animations". Pass the options as "UIViewAnimationOptionCurveEaseOut". Then in the animation block, instead of just changing the frame use "CGAffineTransformMakeScale". Use this for refernce, http://stackoverflow.com/questions/18206430/ios-translation-and-scale-animation – 7vikram7 Jul 01 '16 at 14:52
  • 1
    Thank you bro, with the help from both of you, the problem had solved and I actually come up with another way to achieve the goal. Any others need help could check my github – Di Wang Jul 19 '16 at 18:03
0

When a cell tapped or a button or any tappable thing got tapped inside the cell, then you get the call from didSelectItemAtIndexPath or through delegate, then to give the cell the required size, you have to invalidate the layout of the current collectionview. After this, size for item will get called and give the new size for the,

This will update the size of the collectioncell without reloading it. You can give animation also.

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
        flowLayout.invalidateLayout()
    }

}

0
extension UICollectionView {
            func transactionAnimation(with duration: Float, animateChanges: @escaping () -> Void) {
        
                UIView.animate(withDuration: TimeInterval(duration)) {
                    CATransaction.begin()
                    CATransaction.setAnimationDuration(CFTimeInterval(duration))
                    CATransaction.setAnimationTimingFunction(.init(name: .default))
                    animateChanges()
                    CATransaction.commit()
        
                }
            }
        }
    
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

     collectionView.transactionAnimation(with: 0.3) {
                self.carInfoCollectionView?.performBatchUpdates({}, completion: { _ in })
        
   }
}
Aalaa
  • 55
  • 6