Liquid Bubble swipe effect animation with CollectionView

Namrata Jain
4 min readJul 9, 2020

--

Liquid bubble swipe effect

This is an easy but beautiful animation for showing selected cell in collection view.

So let’s start writing the code…

In Xcode create a Single View App, give the name Animation.

In the Target keep the Deployment Device- ‘iPhone’ and Device Orientation- ‘Portrait’.

Now in ViewController add these:

@IBOutlet weak var photoCollectionView: UICollectionView!@IBOutlet weak var categoryCollectionView: UICollectionView!

And create 2 arrays, 1 for photos and another for categories i.e top collection view.

let photoArray = ["Album4Photo0.jpg", "Album1Photo2.jpg", "Album7Photo2.jpg"]let photoCategoryArray = ["Sunshine", "Butterfly", "PinkSky"]

The photoArray contains the names of images which we will use in our app. You can download these images from here. Drag that downloaded folder in your project.

Open Main.storyboard, drag a collection view and connect it’s IBOutlet to photoCollectionView. Connect it’s delegate and datasource to viewcontroller. In the attribute inspector uncheck scrolling enabled. Only keep ‘paging enabled’ to checked. Last, add constraints:

  1. Leading to safe area.
  2. Trailing to safe area.
  3. Height = 568
  4. Align centre Y to superview with constant = 30.

Drag another collection view and connect it’s IBOutlet to categoryCollectionView. Connect it’s delegate and datasource to viewcontroller. Add constraints:

  1. Leading to safe area.
  2. Trailing to safe area.
  3. Height = 70
  4. Bottom space to photocollectionview.

Now create 2 custom CollectionViewCell class:

class PhotoCell: UICollectionViewCell {    @IBOutlet weak var photoImage: UIImageView!
}
class CategoryCell: UICollectionViewCell { @IBOutlet weak var nameLabel: UILabel!
}

Again open Main.storyboard and do the following:

  1. In the cell of photoCollectionView give the identifier -‘Photo Cell’.
  2. Set the class of cell to ‘PhotoCell’
  3. Drag an image view in this cell. Add constraints to this imageView: Leading, trailing, top and bottom space to superview with constant 0.
  4. Connect the outlet of image view to ‘photoImage’.
  5. Now in CategoryCollectionView, set the cell class to ‘CategoryCell’ and cell identifier -‘CategoryCell’.
  6. Drag a label on the cell. Add constraints to this: Leading, trailing space to superview with constant 20 and top, bottom space to superview with constant 0.
  7. Connect the outlet of label to ‘nameLabel’.

Now open the ViewController implement the delegates of collection view:

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == photoCollectionView {
return photoArray.count
} else {
return photoCategoryArray.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView == photoCollectionView { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Photo Cell", for: indexPath) as! PhotoCell cell.photoImage.image = UIImage(named: photoArray[indexPath.row]) return cell } else { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Category Cell", for: indexPath) as! CategoryCell cell.nameLabel.text = photoCategoryArray[indexPath.row] return cell }
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if collectionView == categoryCollectionView { if let cell = collectionView.cellForItem(at: indexPath) as? CategoryCell { cell.nameLabel.textColor = UIColor(white: 0, alpha: 1.0) let labelPosition = cell.frame.origin.x + 20 photoCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) }
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { if collectionView == categoryCollectionView { if let cell = collectionView.cellForItem(at: indexPath) as? CategoryCell { cell.nameLabel.textColor = UIColor(white: 0, alpha: 0.6) } } }}

Add viewDidAppear function like this:

override func viewDidAppear(_ animated: Bool) {super.viewDidAppear(animated)//Select 1st celllet indexpath = IndexPath(item: 0, section: 0)if let cell = categoryCollectionView.cellForItem(at: indexpath) as? CategoryCell {   categoryCollectionView.selectItem(at: indexpath, animated: false,    scrollPosition: [])   cell.nameLabel.textColor = UIColor(white: 0, alpha: 1.0)  }}

Run the project and see that on tapping any category from top collection view the photo is changing in photo collection view.

Now let’s see the liquid bubble like animation.

Add this below your IBOutlet declaration:

var bubble = UIView(frame: CGRect(x: 0, y: 100, width: 40, height: 40))

Now in viewDidLoad, add this:

self.view.addSubview(bubble)bubble.backgroundColor = UIColor(red: 104/255, green: 134/255, blue: 1, alpha: 1.0)bubble.layer.cornerRadius = 20self.view.bringSubviewToFront(categoryCollectionView)

Update your viewDidAppear with this:

func liquidAnimate(position: CGFloat) {   let midOfNewPostion = (position - self.bubble.frame.origin.x)/2    UIView.animateKeyframes(withDuration: 0.6, delay: 0, options: [.calculationModeLinear], animations: {   UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration:       0.5, animations: {     self.bubble.frame.size.width = 80     self.bubble.frame.origin.x += midOfNewPostion     self.bubble.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)     })      UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: {         self.bubble.transform = CGAffineTransform(scaleX: 1, y: 1)         self.bubble.frame.origin.x += midOfNewPostion         self.bubble.frame.size.width = 40      })    }, completion: { _ in    })}

In the above function, the parameter position is the x-coordinate of the cell in which we need to show the bubble. We used animateWithKeyframes and added 2 keyframe animations in it. Let’s understand what we did in both animations…

The 1st keyframe animation:

  1. Increases the width of bubble frame to 80 from 40
  2. Update the x position of bubble till the half of the total distance we want to shift the bubble.
  3. De-scales the bubble and to half of its size.

The 2nd keyframe animation:

  1. Again decreases the width of bubble frame to 40 from 80.
  2. Update the x position of bubble from the remaining half of the total distance till the total distance we want to shift.
  3. Re-scales the bubble and to half of its actual size.

Now update the didSelectItemAt indexpath function:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == categoryCollectionView {
if let cell = collectionView.cellForItem(at: indexPath) as? CategoryCell {
cell.nameLabel.textColor = UIColor(white: 0, alpha: 1.0) let labelPosition = cell.frame.origin.x + 20 liquidAnimate(position: labelPosition) photoCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) }
}
}

In the above didSelect method, we took out the x-position of cell’s nameLabel and sent that value in the parameter of func liquidAnimate.

So, it’s done. Thank you for reading the tutorial. Hope you enjoyed it.

Final project can be downloaded from here:

https://github.com/namrata1102/LiquidBubbleAnimation.git

--

--