Gradient Layer and Animation Fix
Tinder Firestore Swipe and Match
In this quick lesson, we'll look at how we can implement a nice subtle gradient inside the CardView objects we are presenting for the UI. This is done by adding a sublayer called a CAGradientLayer. You'll then need to set up the correct colors, locations, and frame property to have it show up correctly.

Comments (13)
flashtrend
4 years ago
Hi, really enjoying the videos. Cant wait for the next ones!! How long will the next videos be out in?
Brian Voong
4 years ago
gagarina4
4 years ago
Hi Brian, Really enjoy learning with your lessons. Thanks!
sirybob
4 years ago
Thank you so much Brian! You rock!
alanniba
4 years ago
hey Brian , im trying to add a gradient mask to my custom table view cell , everything works fine on iphone x simulator , but when i change over to another size of simulator, the mask is there but the size is wried. is there any solutions for that ?
BChriss
4 years ago
Why don't you call super.layoutSubviews() (8:18) ? I'm pretty sure that you mentioned to do it in an other course :D
Brian Voong
4 years ago
alix
4 years ago
also, why not call gradient layer function in the layoutDidSubviews() make life much easier. unless you have point to make
Brian Voong
4 years ago
Cinquain
4 years ago
Great video!
Cinquain
4 years ago
Fire!
Chris Davis
4 years ago
Hi Brian, Any suggestions on how would you make the gradientView into a radial gradient?
Chris Davis
4 years ago
Let me get more specific. I tried to implement the following code I found on StackOverflow into the project (as I'm trying to see how some white buttons look at the top corners): https://stackoverflow.com/questions/26907352/how-to-draw-radial-gradients-in-a-calayer/26924839#26924839 It works like a charm, until I try to scroll the sticky header, then the radial gradient sizes in the opposite direction, anchored to point x:0, y:0. I'm not sure how to make the radialGradientView.frame follow the userProfileImage.bounds (if that makes sense..) Please help!
omryno1
4 years ago
Hey Brian, regarding to the solution for the animation glitch, It's seems not very efficient to run through all your subview every time you start a PanGesture. you can remove all layer animations from the last subview in your superview and it would do the trick just the same... superview?.subviews.last?.layer.removeAllAnimations() please correct me if I'm wrong...
DiegoOruna
4 years ago
It makes a lot of sense
BobbyAxelrod
4 years ago
+1 Worked well for me.
David Guarino
3 years ago
Hey I ended up using your solution in the case .handleEnded switch statement. Thanks
Cesar Bess
4 years ago
Hey Brian, I'm not sure if you're going to implement that until lesson 47 but... How can I add more cards behind while swiping? so I'll never run out of cards, and maybe make those cards look like a deck.
alexb
4 years ago
Hi I would like to be able to swipe while in the handleEnded state. So while the card is going back to its stack I should be able to re catch the card and swipe it around instead of having to wait for the animation to end. It is better user experience and the animaitons feels smoother if I don't have to wait for the .ended state to animate fully. I made a post on stackoverflow https://stackoverflow.com/questions/57473406/uipangesturerecognizer-waits-for-animation-to-end-in-ended-state-and-does-not-t
Dino32
3 years ago
Hi! I think I've found the way how it had to been working. Use this line of code at "handleEnded" and you will safe the animation. if shouldDismissCard { self.frame = CGRect(x: 1000 * translationDirection, y: 0, width: self.frame.width, height: self.frame.height) self.superview?.subviews.last?.layer.removeAllAnimations() } else { // bringing back to starting point self.transform = .identity }
Greg Reda
4 years ago
Hey Brian, with the new Xcode update this animation fix no longer fixes the issue. Any idea why the bug is reoccurring and know a good fix to it? Thanks!
David Guarino
3 years ago
Hey Greg found a fix for us....comment out the //"case.began" part Brian implemented and put this under handleEnded(gesture) in "case.ended" switch statement: self.superview?.subviews.last?.layer.removeAllAnimations() Hope this helps. Good Luck
Greg Reda
3 years ago
Thanks, Dave! I'll give it a shot. Was able to figure out a hack solution so let's see if this does the job correctly
Dino32
3 years ago
Thanks David! Your comment is really helpful.
Dino32
3 years ago
David Hi! Do you know how to safe the smooth of animation after adding this code self.superview?.subviews.last?.layer.removeAllAnimations()?
David Guarino
3 years ago
Hey Dino.. This is just a guess but I would say play around with the animate features....I did see that Brian will update the course with changes once Catalina rolls out ( He states it in episode 5 comments)
Dino32
3 years ago
HI David. I think I've found the way how it had to been working. Use this line of code at "handleEnded" and you will safe the animation. if shouldDismissCard { self.frame = CGRect(x: 1000 * translationDirection, y: 0, width: self.frame.width, height: self.frame.height) self.superview?.subviews.last?.layer.removeAllAnimations() } else { // bringing back to starting point self.transform = .identity }
David Guarino
3 years ago
Yup looks good! Thanks ....Right now I'm trying to get this MVVM / Bindable concept to work in an app I've been working on by repeatedly looking at the videos
RobinWorm
3 years ago
Hi, This does not fix it for me, in this way the animation never gets to run and the card just disappears?
Dino32
3 years ago
Robin Hi, The solution have turned out simple. Just add "layer" in self.layer.frame and everything is going to be ok. All the code should looks like this: The first part - @objc func handlePan(gesture: UIPanGestureRecognizer) { switch gesture.state { case .began: self.superview?.subviews.last?.layer.removeAllAnimations() case .changed: handleChanged(gesture) case .ended: handleEnded(gesture) default: () } } and the second fileprivate func handleEnded(_ gesture: UIPanGestureRecognizer) { //set up functionality to dismiss the card from left to right and backwards let translationDirection: CGFloat = gesture.translation(in: nil).x > 0 ? 1 : -1 let shouldDismissCard = abs(gesture.translation(in: nil).x) > threshold UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.1, options: .curveEaseOut, animations: { if shouldDismissCard { self.layer.frame = CGRect(x: 600 * translationDirection, y: 0, width: self.frame.width, height: self.frame.height) //self.superview?.subviews.last?.layer.removeAllAnimations() } else { // bringing back to starting point self.transform = .identity } }) { (_) in self.transform = .identity if shouldDismissCard { self.removeFromSuperview() } } }
RobinWorm
3 years ago
Thank you, adding self.layer indeed fixed it :D
Ally Makongo
3 years ago
If I don't want to apply gradient for the advertiser model, what's the best way to go about it? 1. should I give type value on card view model and hide gradient based on the struct/model?
HELP & SUPPORT