UICollectionViewCell Custom Animation On Tap - swift

My goal is to build a custom cell that, when tapped, animates similar to Snapchat's. I have gotten the animation to work, but as a scroll more (after tap), the last selected cell continues to animate as I tap around the screen. Here's a video example
To get this animation, I am overriding the isSelected value in a custom cell class like so:
override var isSelected: Bool {
didSet {
if isSelected {
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}, completion: { _ in
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 1, y: 1)
}, completion: nil)
})
}
}
}
Please help me figure out why the last selected cell continues to animate even after the correct animation is completed.

Related

how to animate the a particular label from bottom to top in swift

I want to animate label from bottom to top.
I am using this code
UIView.animate(withDuration: 2, delay: 0, options: [.curveEaseOut],
animations: {
quoteLbl.center.y -= self.view.bounds.height - 100
self.view.layoutIfNeeded()
}, completion: nil)
but this code animate the whole view and I want to animate a particular label of UIViewController

Constraint animation doesnt animate y position change

This code is to expand a label by disabling the constraint which is keeping it at a max height of 54 to a full size. It works as it should but it jumps to the new y position straight away (without animating) and changes frame height after which makes it look like it jumps before animating
#IBOutlet var descriptionHeightConstraint: NSLayoutConstraint!
#IBAction func toggleFullDescription(_ sender: Any) {
if descriptionHeightConstraint.isActive {
self.layoutIfNeeded()
descriptionHeightConstraint.isActive = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.layoutIfNeeded()
}, completion: nil)
//seeMoreButton.setTitle("See less", for: .normal)
} else {
self.layoutIfNeeded()
descriptionHeightConstraint.isActive = true
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseInOut, animations: {
self.layoutIfNeeded()
}, completion: nil)
//seeMoreButton.setTitle("See more", for: .normal)
}
}
Video of the issue

UI Animation using animateKeyframes does nothing to Button Title Color

I'm trying to animate the color of my UIButton Title Color using animateKeyframes but it does nothing except load the last state in the animation, in this case purpleText. I'm using the same code to animate button colors and a UIView background color without any issues.
I checked also changed the button to a custom button in Interface Builder but that didn't help either.
UIView.animateKeyframes(withDuration: 12, delay: 12, options: [.allowUserInteraction, .repeat, .autoreverse], animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(blueText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.2, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(greenText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.4, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(yellowText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.6, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(redText, for: UIControlState.normal)
})
UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 0.25, animations: {
self.infoButton.setTitleColor(purpleText, for: UIControlState.normal)
})
}, completion: nil)
Calling setTitleColor() inside the animation block doesn't work because UIView.animate only works on animatable properties, like infoButton.backgroundColor.
Unfortunately, button properties like tintColor aren't animatable. You also shouldn't directly access the button's titleLabel, which is nil for system buttons.
Instead, you can use UIView.transition with setTitleColor(). You can then put it inside a Timer... I usually don't like to use timers for animations, but I can't think of any other way.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let colors: [UIColor] = [.blue, .green, .yellow, .red, .purple]
var currentIndex = 0
_ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
if colors.indices.contains(currentIndex) {
UIView.transition(with: self.infoButton, duration: 0.5, options: [.transitionCrossDissolve, .allowUserInteraction]) {
self.infoButton.setTitleColor(colors[currentIndex], for: .normal)
}
currentIndex += 1
} else {
currentIndex = 0
}
}
}
Result:

UIButton Animations not working on UIScrollView

I have button animations that are not working on my ScrollView. I have other VCs that are just UIViews and animations work just fine.
So I tried unchecking from the Attributes Inspector and adding...
self.scrollView.delaysContentTouches = false
...in my viewDidLoad, but it had effect.
I also found that tapping does not trigger the animation but holding on the button for a second or more does and haptic presses also trigger the animation.
This is my animation code:
extension UIButton {
func startAnimatingPressActions() {
addTarget(self, action: #selector(animateDown), for: [.touchDown, .touchDragEnter])
addTarget(self, action: #selector(animateUp), for: [.touchDragExit, .touchCancel, .touchUpInside, .touchUpOutside])
}
#objc private func animateDown(sender: UIButton) {
animate(sender, transform: CGAffineTransform.identity.scaledBy(x: 0.95, y: 0.95))
}
#objc private func animateUp(sender: UIButton) {
animate(sender, transform: .identity)
}
private func animate(_ button: UIButton, transform: CGAffineTransform) {
UIView.animate(withDuration: 0.4,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 3,
options: [.curveEaseInOut],
animations: {
button.transform = transform
}, completion: nil)
}
}
I am able to get this animation working, but it doesn't feel quite right. So I'd rather not use the code below. But it does work. So I'm not sure what in the code above is causing the problem.
extension UIButton {
func pulsate() {
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.duration = 0.2
pulse.fromValue = 0.96
pulse.toValue = 1.0
pulse.repeatCount = 0
pulse.initialVelocity = 0.5
pulse.damping = 1.0
layer.add(pulse, forKey: nil)
}
}
I had the same issue and I solved unchecking the delay touch down button in the scrollview's attributes inspector :
ScrollView's attrobutes inspector

UIButton resize animation is not animating

I'm trying to make that my button double its size using the UIView animation, but for some reason it is not working it the size goes right, but no animated.
The function that should animate the button resizing
Irrelevant code above
#objc func createButtonPressed(){
//Removes the bottom stack with buttons
if let stackButton = self.view.viewWithTag(50){
stackButton.removeFromSuperview()
}
//Add the button back with half ares size
bottomHolder.addSubview(rightButton)
rightButton.setImage(nil, for: .normal)
rightButton.addTarget(self, action: #selector(anima), for: .touchUpInside)
rightButton.topAnchor.constraint(equalTo: bottomHolder.topAnchor).isActive = true
rightButton.trailingAnchor.constraint(equalTo: bottomHolder.trailingAnchor).isActive = true
rightButton.bottomAnchor.constraint(equalTo: bottomHolder.bottomAnchor).isActive = true
}
#objc func anima(){
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.rightButton.leadingAnchor.constraint(equalTo: self.bottomHolder.leadingAnchor).isActive = true
self.rightButton.layoutIfNeeded()
}, completion: nil)
}
Irrelevant code below
try this one:
let buttonFinalWidth = UIScreen.main.bounds.width
DispatchQueue.main.async {
UIView.animate(withDuration: 5.0) {
self.rightButton.widthAnchor.constraint(equalToConstant: buttonFinalWidth).isActive = true
self.view.layoutIfNeeded()
}
}