Hello, folks! It’s been a long time for me to be away from the thing I Love! Writing.I would never say that if the deal was with a pen and paper 😅.I am back with some proper blogging schedule in my mind, So let’s get started.
Peek and Pop is there in many apps like Instagram and WhatsApp. What’s stopping us from building it in our apps? Having something playful at your fingertips is good, and I would say Peek and Pop is not just an animated feature, but it also gives us an option to quickly add some actions onto our preview without presenting the view controller.
Getting Started
I know setting up the project is quite dull. You can simply skip the Getting Started section by downloading the starter project here and follow along from the next section Peek and Pop.
Let’s set up our project before we can Peek and Pop, Create a new UIKit Project, then in your Main.storyboard
file, Embed a Navigation Controller by selecting the ViewController and then in the top bar Click on Editor -> Embed In -> Navigation Controller. Next, Drag and Drop a UICollectionView
in your ViewController.
Now, let’s modify the collection view cell by adding a label in it with Horizontally in Container and Vertically in Container constraints. Your final design should look something like the image shown below.
In the Size Inspector, set the Min Spacing to 0 for both cells and lines, as shown in the screenshot below.
Tip: To add emoji to your Label, press Command + Control + Space
Now, let’s create a UICollectionViewCell
subclass, name it PeekAndPopCollectionViewCell
. Next, select the cell in your ViewController, and in Attribute Inspector, give it an identifier cell
. Next, in your Identity Inspector, add the class you just created in the class field.
Next, select your cell, then open the Assistant Editor and navigate to PeekAndPopCollectionViewCell
, create an IBOutlet
of the label, and name it emojiLabel
.
Next, create an IBOutlet
for your collection view in your ViewController.swift
file.
Now, Drag and Drop a UIViewController
in your Main.storyboard
file, and create a UIViewController
subclass, name it EmojiViewController
. Link your class with the UIViewController
you just added, drag and drop a UILabel
in it, modify the label to have a font size of 120. Add the constraints for center alignment. Create an IBOutlet
for the same and name it emojiLabel
.
Your final UI should look like the screenshot shown below.
Final Step
Add the line given below in your ViewController.swift
file.
let emojis = ["😃", "🤣", "😍", "😘", "🥳", "🥺"]
Next, add the line given below in your EmojiViewController.swift
file.
var emoji = ""
Note: The code above is to be added as global properties.
Next, in your viewDidLoad()
of EmojiViewController.swift
file, add the line given below.
self.emojiLabel.text = emoji
We are ready to move to our next section, Peek and Pop.
Peek and Pop
Let’s set up our collection view to Peek and Pop. We will be setting our delegate and data source of the collection view in the viewDidLoad()
of the ViewController.swift
file.
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
Next, create an extension of ViewController for our delegate and data source functions, as shown below.
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.emojis.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width: self.view.frame.width/3, height: self.view.frame.width/3)
return size
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! PeekAndPopCollectionViewCell
cell.emojiLabel.text = self.emojis[indexPath.item]
return cell
}
}
We only need two functions more to enable the Peek and Pop feature. Let’s start with the first one.
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let config = UIContextMenuConfiguration(identifier: indexPath as NSIndexPath, previewProvider: { () -> UIViewController? in
let emojiVC = self.storyboard?.instantiateViewController(withIdentifier: "EmojiViewController") as! EmojiViewController
emojiVC.emoji = self.emojis[indexPath.item]
return emojiVC
}, actionProvider: nil)
return config
}
Here, the function needs a return value of type UIContextMenuConfiguration
, and we do that by initializing the configuration with an identifier (takes an object which conforms to NSCopying
protocol), previewProvider (here we pass our destination view controller) and actionProvider (this we will keep nil for now, and explore it in the next section).
For identifier, we are passing indexPath and make sure the type is converted to NSIndexPath. As identifier only takes an object which conforms to NSCopying
protocol.
In the previewProvider argument, we are executing a block where our destination view controller is instantiated, and the selected index emoji is associated with its emoji
property.
Now let’s add our final function, which will do the charm of adding our destination view controller into our navigation stack in case the user wants to open the screen.
func collectionView(_ collectionView: UICollectionView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
guard let vc = animator.previewViewController else { return }
animator.addCompletion {
self.navigationController?.pushViewController(vc, animated: true)
}
}
guard
here ensures that our previewViewController is not nil before pushing the destination view controller (EmojiViewController).
Let’s run the app and see how it works.
Well! That’s how you Peek and Pop 😁. Now, Let’s look at how do we add actions to them.
Adding Actions
I like how Apple provides us with the actions menu in the preview to get things done quickly, and it doesn’t require much coding. Replace the function below and rerun the app to see the actions live.
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let config = UIContextMenuConfiguration(identifier: indexPath as NSIndexPath) { () -> UIViewController? in
let emojiVC = self.storyboard?.instantiateViewController(withIdentifier: "EmojiViewController") as! EmojiViewController
emojiVC.emoji = self.emojis[indexPath.item]
return emojiVC
} actionProvider: { (actions) -> UIMenu? in
let okayElement = UIAction(title: "Like", image: nil, identifier: nil) { (action) in
// Do something
}
let menu = UIMenu(title: "", children: [okayElement])
return menu
}
return config
}
This is all it takes to add an action(s) into our preview. Now, let’s look at the Bonus section to add Peek and Pop functionality into a table view.
Bonus
Adding Peek and Pop in the collection view was easy. With just two functions, we were up and running. Can we achieve the same with UITableView
?
Well, Yes, we have similar functions for the table view listed below
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?
func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating)