Cell Shadows and Press Down Animations
AppStore JSON APIs
As a general rule of thumb, its never a good idea to implement small minor visual enhancements until your application is finished. Because we're in the home stretch of the development lifecycle, I think its a good idea to add a little bit of pop to our UI just to make it stand out. In this lesson, I'll go over how to implement shadows in your app as well as a press down animation for cells. Enjoy.

Comments (11)
Tube
4 years ago
Still responsive. Daily List doesn't shrink on tap if you tap in the list on the card.
Brian Voong
4 years ago
ncytimothy
4 years ago
Hi Brian, this is quite subtle, but I noticed the actual App Store actually shrinks the cell a bit whenever the cell is tapped (even during the scroll)! Looks like the implementation here will make the user apply an explicit touch event for the first shrink to happen and the full screen details controller to come in. I am still researching on how to replicate such minute interaction in my cell, appreciate if you may guide me somewhere!
สรรพสิทธิ์ ศรีแสง
4 years ago
For someone who got question about super.init, This article explains how its work. https://medium.com/@dineshk1389/swift-why-super-init-is-called-after-setting-all-self-properties-d6827e9f4eb2
malrhex
4 years ago
I did the BaseCell and just implemented on my actual cell and all those tricks with the shadows didn't work. Or I clip to bounds and have nice corners or I have the shadows, but I can't mix both some weird behaviors
malrhex
4 years ago
I want to delete this comment, haha now it's working just removed my gradient layers on the cell
Stewart Lynch
4 years ago
I refactored the isHighlighted code this instead. Even shorter. override var isHighlighted: Bool { didSet { UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { self.transform = self.isHighlighted ? .init(scaleX: 0.9, y: 0.9) : .identity }) } }
jdhindsa
4 years ago
Brian please help me! How would a newbie ever know about the various properties you are using to modify these views to get them to look how you want? The developer documentation is not written in a way where you can easily deduce what the property is for. Are you spending hours on end trying to find which properties to use? Ie. how did you know that you needed to set the background view in BaseTodayCell?
Brian Voong
4 years ago
Mohamed Ibrahim Fetyany
3 years ago
hi brain thank you for this work and hope you're good I'm using ios 13 and in TodayMultipleAppsController in didSelectItemAt IndexPath and try to open AppDetailsController it didn't work with navigationController?.pushViewController(appDetailController, animated: true) and work fine with present( appDetailController, animated: true) but I can not go back and second, the class BackEnabledNavigationController didn't open the view controller with full screen and I'm set myViewController.modalPresentationStyle = .fullScreen but didn't work
ZeroSingularity
3 years ago
You can achieve the desired result in iOS 13 like this. You have to make sure that the modalPresentation style that you're changing to .fullScreen is being set on the proper viewController. In other words, make sure to set .fullScreen on the UINavigationController instead since it's the one being presented and because it's the parent of myViewController. @objc fileprivate func handleMultipleAppsTap(gesture: UIGestureRecognizer) { let collectionView = gesture.view var superview = collectionView?.superview while superview != nil { if let cell = superview as? TodayMultipleAppCell { guard let indexPath = self.collectionView.indexPath(for: cell) else { return } let appFullscreenController = TodayMultipleAppsController(mode: .fullscreen) let fullscreenNavigationController = BackEnabledNavigationController(rootViewController: appFullscreenController) appFullscreenController.apps = self.items[indexPath.item].apps fullscreenNavigationController.modalPresentationStyle = .fullScreen navigationController?.present(fullscreenNavigationController, animated: true) return } superview = superview?.superview } }
Juanpablo Macias
3 years ago
Thank you for getting into the details!
dennis
3 years ago
Hello Brian, I was not able to set the shadow on the self.backgroundView?.layer. When I set the background color to white the cell is empty. If i remove the backgroundColor on the backgroundView i can see the cell elements again, but not the shadow. Is this an iOS 13 issue?
sannchhailong
2 years ago
I found that if I add 'self.collectionView.isUserInteractionEnabled = mode == .fullscreen' to viewDidLoad() in TodayMultipleAppsController, I don't need to add TapGestureRecognizer to collectionView in cellForRowAt(indexpath:) in TodayController. Let me know if my method is affecting to other features.
Ata Etgi
2 years ago
There is a better way to make sharper texts after rasterizing layers. We can add rasterization scale for screen like this: layer.shadowOpacity = 0.1 layer.shadowRadius = 10 layer.shadowOffset = .init(width: 0, height: 10) layer.shadowPath = UIBezierPath(rect: layer.bounds).cgPath layer.rasterizationScale = UIScreen.main.scale // you should make sure iOS caches the shadow at the same drawing scale as the main screen, otherwise it look pixelated layer.shouldRasterize = true
HELP & SUPPORT