Making an animation to expand and shrink an UIView - ios

I want to create an animation that will resize an UIView and its contents by a factor. Basically, I want to make an animation that first expands the view then shrinks it back to the original size.
What is the best way to do this? I tried CALayer.contentScale but it didn't do anything at all.

You can nest some animation blocks together like so:
Objective-C:
[UIView animateWithDuration:1
animations:^{
yourView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:^(BOOL finished) {
[UIView animateWithDuration:1
animations:^{
yourView.transform = CGAffineTransformIdentity;
}];
}];
Swift 2:
UIView.animateWithDuration(1, animations: { () -> Void in
yourView.transform = CGAffineTransformMakeScale(1.5, 1.5)
}) { (finished: Bool) -> Void in
UIView.animateWithDuration(1, animations: { () -> Void in
yourView.transform = CGAffineTransformIdentity
})}
Swift 3/4/5:
UIView.animate(withDuration: 1, animations: {
yourView.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
}) { (finished) in
UIView.animate(withDuration: 1, animations: {
yourView.transform = CGAffineTransform.identity
})
}
and replacing the scale values and durations with your own.

Here is a smaller approach that also loops:
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
yourView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
The option UIViewKeyframeAnimationOptionRepeat is what makes it loop, if you don't want it to keep "breathing". The animation block acts as the "inhale" and the UIViewKeyframeAnimationOptionAutoreverse option automatically plays the "exhale" animation.

Swift 5 UIView extension:
extension UIView {
func pulse(withIntensity intensity: CGFloat, withDuration duration: Double, loop: Bool) {
UIView.animate(withDuration: duration, delay: 0, options: [.repeat, .autoreverse], animations: {
loop ? nil : UIView.setAnimationRepeatCount(1)
self.transform = CGAffineTransform(scaleX: intensity, y: intensity)
}) { (true) in
self.transform = CGAffineTransform.identity
}
}
}
And then use the following:
yourView.pulse(withIntensity: 1.2, withDuration: 0.5, loop: true)
Just make sure you replace yourView with your own view.

Related

UIView animate - Rotate and scale up, then rotate and scale down

I have a subclassed imageview that I'd like to fade in, scale up, and rotate, then continue rotating while scaling back down and fading out.
I am using a UIView animate block with a completion handler to handle the shrinking back down.
The problem is it's not a fluid animation. Before the completion handler runs, the animation stops before running again. I need it to be one nice "swoop" of an animation.
Code below:
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
UIView.animate(withDuration: duration * 3, delay: 0, options: [.curveLinear], animations: {
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration * 3, delay: 0.0, options: [.curveLinear], animations: {
self.transform = rotate
}, completion: nil)
// scaling and fading
UIView.animate(withDuration: duration, delay: 0, options: [.curveLinear], animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration, animations: {
UIView.setAnimationRepeatCount(3)
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}, completion: nil)
How can I get the animation to rotate the entire time while fading in and scaling up before scaling back down and fading out? The entire animation should last 3 seconds, and repeat 3 times. Thanks.
For your modified request I am expanding what you already saw using the block animations. As some have said, key frame animations may be better, regardless, here is the thought.
Create an animation that rotates the entire time by transforming the view.
Create another animation that does the scaling and fading based off the current transform (which is rotating). In this pass, I just created some variable to allow you to customize (and repeat) portions of the animation. I broke some things out to be clear and know I could refactor to write thing even more concise.
Here is the code
import UIKit
class OrangeView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 9.0
self.transform = CGAffineTransform.identity
// initial transform
self.alpha = 1
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// start rotation
rotate(duration: duration)
// scaling and fading
scaleUpAndDown(desiredRepetitions: 3, initalDuration: duration)
}
func rotate(duration: TimeInterval) {
UIView.animate(withDuration: duration/2.0,
delay: 0.0,
options: [.curveLinear], animations: {
let angle = Double.pi
self.transform = self.transform.rotated(by: CGFloat(angle))
}, completion: {[weak self] finished in
guard let strongSelf = self else {
return
}
if finished &&
strongSelf.transform != CGAffineTransform.identity {
strongSelf.rotate(duration: duration)
} else {
// rotation ending
}
})
}
func scaleUpAndDown(timesRepeated: Int = 0, desiredRepetitions: Int, initalDuration: TimeInterval) {
guard timesRepeated < desiredRepetitions,
desiredRepetitions > 0, initalDuration > 0 else {
self.transform = CGAffineTransform.identity
return
}
let repeatedCount = timesRepeated + 1
let scalingDuration = initalDuration/2.0/Double(desiredRepetitions)
UIView.animate(withDuration: scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.8
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration:scalingDuration,
delay: 0.0,
animations: {
let desiredOriginalScale: CGFloat = 0.1
let scaleX = abs(CGAffineTransform.identity.a / self.transform.a) * desiredOriginalScale
let scaleY = abs(CGAffineTransform.identity.d / self.transform.d) * desiredOriginalScale
self.transform = self.transform.scaledBy(x: scaleX, y: scaleY)
self.alpha = 0
}) { finshed in
self.scaleUpAndDown(timesRepeated: repeatedCount, desiredRepetitions: desiredRepetitions, initalDuration: initalDuration);
}
}
}
}
Finally here is another animated gif
I see the slight stutter in rotation at the start of the onCompletion.
I created a reduction with your code (shown below in the Blue View) and a variation in the Orange View. This was taken from the simulator and turned into an animated GIF, so speed is slowed down. The Orange View continues to spin as the complete transform just scales down.
This is the code for the layoutSubviews() for the Orange View
override func layoutSubviews() {
super.layoutSubviews()
let duration: TimeInterval = 3.0
let rotate = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
// initial transform
self.alpha = 0
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
// initial spin for duration of animaton
UIView.animate(withDuration: duration,
delay: 0.0,
options: [.curveLinear],
animations: {
self.transform = rotate;
},
completion: nil)
// scaling and fading
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.8, y: 0.8)
self.alpha = 1
}) { (true) in
UIView.animate(withDuration: duration/2.0, animations: {
self.transform = self.transform.scaledBy(x: 0.1, y: 0.1)
self.alpha = 0
})
}
}
Try using CGAffineTransformConcat()
CGAffineTransform scale = CGAffineTransformMakeScale(0.8, 0.8);
self.transform = CGAffineTransformConcat(CGAffineTransformRotate(self.transform, M_PI / 2), scale);

How to zoom in the content of cell in uicollectionview

In the above image,A,B,C,D,E are each custom cell,of collection view and i want to zoom in the cell one by one like c cell.
Any suggestion?
Just call this method when your collectionviewcell click
[self animateZoomforCell:cell]; // pass cell as collectionviewcell
-(void)animateZoomforCell:(UICollectionViewCell*)zoomCell
{
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
zoomCell.transform = CGAffineTransformMakeScale(1.6,1.6);
} completion:^(BOOL finished){
}];
}
-(void)animateZoomforCellremove:(UICollectionViewCell*)zoomCell
{
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
zoomCell.transform = CGAffineTransformMakeScale(1.0,1.0);
} completion:^(BOOL finished){
}];
}
In swift 3 based on Himanshu Moradiya solution:
func animateZoomforCell(zoomCell : UICollectionViewCell)
{
UIView.animate(
withDuration: 0.2,
delay: 0,
options: UIViewAnimationOptions.curveEaseOut,
animations: {
zoomCell.transform = CGAffineTransform.init(scaleX: 1.2, y: 1.2)
},
completion: nil)
}
func animateZoomforCellremove(zoomCell : UICollectionViewCell)
{
UIView.animate(
withDuration: 0.2,
delay: 0,
options: UIViewAnimationOptions.curveEaseOut,
animations: {
zoomCell.transform = CGAffineTransform.init(scaleX: 1.0, y: 1.0)
},
completion: nil)
}

Scale UIButton Animation- Swift [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm trying to do scale animation for UIButton when its clicked but what I'm trying to accomplish is when the button clicked I need the UIButton to be smaller to the inside then it comes back to its same size (like a bubble).
I tried the following:
button.transform = CGAffineTransformMakeScale(-1, 1)
UIView.animateWithDuration(0.5, animations: { () -> Void in
button.transform = CGAffineTransformMakeScale(1,1)
})
Try this
UIView.animate(withDuration: 0.6,
animations: {
self.button.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
},
completion: { _ in
UIView.animate(withDuration: 0.6) {
self.button.transform = CGAffineTransform.identity
}
})
SWIFT 5 Code Update :I have animated button with a nice bouncing effect , with spring animation.
#IBOutlet weak var button: UIButton!
#IBAction func animateButton(sender: UIButton) {
sender.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
UIView.animate(withDuration: 2.0,
delay: 0,
usingSpringWithDamping: CGFloat(0.20),
initialSpringVelocity: CGFloat(6.0),
options: UIView.AnimationOptions.allowUserInteraction,
animations: {
sender.transform = CGAffineTransform.identity
},
completion: { Void in() }
)
}
All of the answers above are valid.
As a plus, with Swift I suggest to create an extension of UIView in order to "scale" any view you want.
You can take inspiration from this piece of code:
SWIFT 5.0
extension UIView {
/**
Simply zooming in of a view: set view scale to 0 and zoom to Identity on 'duration' time interval.
- parameter duration: animation duration
*/
func zoomIn(duration: TimeInterval = 0.2) {
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
UIView.animate(withDuration: duration, delay: 0.0, options: [.curveLinear], animations: { () -> Void in
self.transform = .identity
}) { (animationCompleted: Bool) -> Void in
}
}
/**
Simply zooming out of a view: set view scale to Identity and zoom out to 0 on 'duration' time interval.
- parameter duration: animation duration
*/
func zoomOut(duration : TimeInterval = 0.2) {
self.transform = .identity
UIView.animate(withDuration: duration, delay: 0.0, options: [.curveLinear], animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
}) { (animationCompleted: Bool) -> Void in
}
}
/**
Zoom in any view with specified offset magnification.
- parameter duration: animation duration.
- parameter easingOffset: easing offset.
*/
func zoomInWithEasing(duration: TimeInterval = 0.2, easingOffset: CGFloat = 0.2) {
let easeScale = 1.0 + easingOffset
let easingDuration = TimeInterval(easingOffset) * duration / TimeInterval(easeScale)
let scalingDuration = duration - easingDuration
UIView.animate(withDuration: scalingDuration, delay: 0.0, options: .curveEaseIn, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: easeScale, y: easeScale)
}, completion: { (completed: Bool) -> Void in
UIView.animate(withDuration: easingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = .identity
}, completion: { (completed: Bool) -> Void in
})
})
}
/**
Zoom out any view with specified offset magnification.
- parameter duration: animation duration.
- parameter easingOffset: easing offset.
*/
func zoomOutWithEasing(duration: TimeInterval = 0.2, easingOffset: CGFloat = 0.2) {
let easeScale = 1.0 + easingOffset
let easingDuration = TimeInterval(easingOffset) * duration / TimeInterval(easeScale)
let scalingDuration = duration - easingDuration
UIView.animate(withDuration: easingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: easeScale, y: easeScale)
}, completion: { (completed: Bool) -> Void in
UIView.animate(withDuration: scalingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
}, completion: { (completed: Bool) -> Void in
})
})
}
}
Usage is very simply:
let button = UIButton(frame: frame)
button.zoomIn() // here the magic
Swift 3 Version
extension UIView {
/**
Simply zooming in of a view: set view scale to 0 and zoom to Identity on 'duration' time interval.
- parameter duration: animation duration
*/
func zoomIn(duration: TimeInterval = 0.2) {
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
UIView.animate(withDuration: duration, delay: 0.0, options: [.curveLinear], animations: { () -> Void in
self.transform = CGAffineTransform.identity
}) { (animationCompleted: Bool) -> Void in
}
}
/**
Simply zooming out of a view: set view scale to Identity and zoom out to 0 on 'duration' time interval.
- parameter duration: animation duration
*/
func zoomOut(duration: TimeInterval = 0.2) {
self.transform = CGAffineTransform.identity
UIView.animate(withDuration: duration, delay: 0.0, options: [.curveLinear], animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
}) { (animationCompleted: Bool) -> Void in
}
}
/**
Zoom in any view with specified offset magnification.
- parameter duration: animation duration.
- parameter easingOffset: easing offset.
*/
func zoomInWithEasing(duration: TimeInterval = 0.2, easingOffset: CGFloat = 0.2) {
let easeScale = 1.0 + easingOffset
let easingDuration = TimeInterval(easingOffset) * duration / TimeInterval(easeScale)
let scalingDuration = duration - easingDuration
UIView.animate(withDuration: scalingDuration, delay: 0.0, options: .curveEaseIn, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: easeScale, y: easeScale)
}, completion: { (completed: Bool) -> Void in
UIView.animate(withDuration: easingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = CGAffineTransform.identity
}, completion: { (completed: Bool) -> Void in
})
})
}
/**
Zoom out any view with specified offset magnification.
- parameter duration: animation duration.
- parameter easingOffset: easing offset.
*/
func zoomOutWithEasing(duration: TimeInterval = 0.2, easingOffset: CGFloat = 0.2) {
let easeScale = 1.0 + easingOffset
let easingDuration = TimeInterval(easingOffset) * duration / TimeInterval(easeScale)
let scalingDuration = duration - easingDuration
UIView.animate(withDuration: easingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: easeScale, y: easeScale)
}, completion: { (completed: Bool) -> Void in
UIView.animate(withDuration: scalingDuration, delay: 0.0, options: .curveEaseOut, animations: { () -> Void in
self.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
}, completion: { (completed: Bool) -> Void in
})
})
}
}
Swift 3.x+
extension UIButton {
func pulsate() {
let pulse = CASpringAnimation(keyPath: "transform.scale")
pulse.duration = 0.2
pulse.fromValue = 0.95
pulse.toValue = 1.0
pulse.autoreverses = true
pulse.repeatCount = 2
pulse.initialVelocity = 0.5
pulse.damping = 1.0
layer.add(pulse, forKey: "pulse")
}
func flash() {
let flash = CABasicAnimation(keyPath: "opacity")
flash.duration = 0.2
flash.fromValue = 1
flash.toValue = 0.1
flash.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
flash.autoreverses = true
flash.repeatCount = 3
layer.add(flash, forKey: nil)
}
func shake() {
let shake = CABasicAnimation(keyPath: "position")
shake.duration = 0.05
shake.repeatCount = 2
shake.autoreverses = true
let fromPoint = CGPoint(x: center.x - 5, y: center.y)
let fromValue = NSValue(cgPoint: fromPoint)
let toPoint = CGPoint(x: center.x + 5, y: center.y)
let toValue = NSValue(cgPoint: toPoint)
shake.fromValue = fromValue
shake.toValue = toValue
layer.add(shake, forKey: "position")
}
}
Usage:
myButton.flash()
// myButton.pulsate()
// myButton.shake()
Credits: Sean Allen
Swift 3 Version:
UIView.animate(withDuration: 0.6, animations: {
button.transform = CGAffineTransform.identity.scaledBy(x: 0.6, y: 0.6)
}, completion: { (finish) in
UIView.animate(withDuration: 0.6, animations: {
button.transform = CGAffineTransform.identity
})
})
Using Swift 4 Xcode 9, This will animate the button down when initially pressed and then back up when released.
extension UIView {
func animateButtonDown() {
UIView.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseIn], animations: {
self.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
}, completion: nil)
}
func animateButtonUp() {
UIView.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseOut], animations: {
self.transform = CGAffineTransform.identity
}, completion: nil)
}
Implementation:
#IBAction func buttonTouchDown(_ sender: UIButton) {
//Connected with Touch Down Action
sender.animateButtonDown()
}
#IBAction func buttonTouchUpOutside(_ sender: UIButton) {
//Connected with Touch Up Outside Action
//if touch moved away from button
sender.animateButtonUp()
}
#IBAction func buttonTouchUpInside(_ sender: UIButton) {
//Connected with Touch Up Inside Action
sender.animateButtonUp()
//code to execute when button pressed
}
It works with me as following, the animation is set to be small then when it start animation it get back to its original size:
Swift 2
button.transform = CGAffineTransformMakeScale(0.6, 0.6)
UIView.animateWithDuration(0.3, animations: { () -> Void in
button.transform = CGAffineTransformMakeScale(1,1)
})
Swift 3, 4, 5
button.transform = CGAffineTransform.init(scaleX: 0.6, y: 0.6)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
button.transform = CGAffineTransform.init(scaleX: 1, y: 1)
})
I prefer to have the press animation and set it more fast than the other examples, with the completion control for waiting until the animation is ended:
Swift 3:
extension UIButton {
func press(completion:#escaping ((Bool) -> Void)) {
UIView.animate(withDuration: 0.05, animations: {
self.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) }, completion: { (finish: Bool) in
UIView.animate(withDuration: 0.1, animations: {
self.transform = CGAffineTransform.identity
completion(finish)
})
})
}
}
Usage:
#IBAction func playPauseBtnTap(_ sender: Any) {
let playPauseBtn = sender as! UIButton
playPauseBtn.press(completion:{ finish in
if finish {
print("animation ended")
}
}
}
Using the following animation the button will start from its full size, decrease to 0.6 with a spring animation to bounce back to it's full size.
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:0.3 options:0 animations:^{
//Animations
button.transform = CGAffineTransformIdentity;
CGAffineTransformMakeScale(0.6, 0.6)
} completion:^(BOOL finished) {
//Completion Block
[UIView.animateWithDuration(0.5){
button.transform = CGAffineTransformIdentity
}];
}];
You can try this if you want a Autoreverse effect with a completion handler.
viewToAnimate.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
UIView.animate(withDuration: 0.7, // your duration
delay: 0,
usingSpringWithDamping: 0.2,
initialSpringVelocity: 6.0,
animations: { _ in
viewToAnimate.transform = .identity
},
completion: { _ in
// Implement your awesome logic here.
})
iOS 9 and xCode 7
//for zoom in
[UIView animateWithDuration:0.5f animations:^{
self.sendButton.transform = CGAffineTransformMakeScale(1.5, 1.5);
} completion:^(BOOL finished){}];
// for zoom out
[UIView animateWithDuration:0.5f animations:^{
self.sendButton.transform = CGAffineTransformMakeScale(1, 1);
}completion:^(BOOL finished){}];
This will give a wonderful bouncing effect:
#IBAction func TouchUpInsideEvent(sender: UIButton) {
UIView.animateWithDuration(2.0,
delay: 0,
usingSpringWithDamping: CGFloat(0.20),
initialSpringVelocity: CGFloat(6.0),
options: UIViewAnimationOptions.AllowUserInteraction,
animations: {
sender.transform = CGAffineTransformIdentity
},
completion: { Void in() }
)
}
#IBAction func touchDownEvent(sender: UIButton) {
UIView.animateWithDuration(0.15, animations: {
sender.transform = CGAffineTransformMakeScale(0.6, 0.6)
})
}
Scaling Button or any view about three times or more use following code. swift 3 or swift 4 with xcode 9.
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
}, completion: { (finish: Bool) in
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform.identity
}, completion:{(finish: Bool) in
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
}, completion: { (finish: Bool) in
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform.identity
}, completion:{(finish: Bool) in
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
}, completion: { (finish: Bool) in
UIView.animate(withDuration: 0.2, animations: {
self.cartShowHideBtnView.transform = CGAffineTransform.identity
})
})
})
})
})
})
I did a protocol using Swift 4, that you can use at some specifics UIViews that you want to animate... You can try some animations over here or change time and delay.
This way is recommended because you can use this protocol and others at one view and this view can use this functions, doing a lot os extensions from UIView create code smell.
import Foundation
import UIKit
protocol Showable where Self: UIView {}
extension Showable {
func show(_ view: UIView? = nil) {
if let view = view {
self.animate(view)
} else {
self.animate(self)
}
}
private func animate(_ view: UIView) {
view.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
UIView.animate(withDuration: 2.0,
delay: 0,
usingSpringWithDamping: CGFloat(0.20),
initialSpringVelocity: CGFloat(6.0),
options: [.allowUserInteraction],
animations: {
view.transform = CGAffineTransform.identity
})
}
}
Here is a working example :
extension UIButton{
func flash() {
let flash = CABasicAnimation(keyPath: "opacity")
flash.duration = 0.5
flash.fromValue = 1
flash.toValue = 0.1
flash.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
flash.autoreverses = true
flash.repeatCount = 3
layer.add(flash, forKey: nil)
}
}
#IBAction func taptosave(_ sender: UIButton) {
sender.flash()
}

Multiple UIView Animations

I have a UIButton that I have placed in the center of the screen using Interface Builder.
I want to animate the UIButton to move up and down and repeat the animation forever.
So far I have this in my didMoveToView:
UIView.animateWithDuration(3, animations: { () -> Void in
self.playBtn.transform = CGAffineTransformMakeTranslation(0, 10)
self.playBtn.transform = CGAffineTransformMakeTranslation(0, -10)
self.playBtn.transform = CGAffineTransformMakeTranslation(0, -10)
self.playBtn.transform = CGAffineTransformMakeTranslation(0, 10)
UIView.setAnimationRepeatCount(-1)
})
However it only runs the first line and moves the button down 10.
You can't change the transform to multiple things simultaneously. I would expect your code to cause no animation at all, as changing the transform more than once would cancel the animation.
Another problem with your code is that what you're saying is not how you ask for a repeating animation.
Still another problem is that you won't ever bring the button back to its starting place; the transforms are not additive.
What you need to do is chain animations together. This will be easiest if you drop down to Core Animation and make a grouped animation.
Or can do it with view animation by doing a keyframe animation, perhaps; this is not identical to what you want, but it will get you started:
Swift 2
let opts = UIViewKeyframeAnimationOptions.Repeat
UIView.animateKeyframesWithDuration(3, delay: 0, options: opts, animations: {
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.5, animations: {
self.playBtn.transform = CGAffineTransformMakeTranslation(0, 10)
})
UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.5, animations: {
self.playBtn.transform = CGAffineTransformIdentity
})
}, completion: nil)
Swift 3,4,5
let opts = UIView.KeyframeAnimationOptions.repeat
UIView.animateKeyframes(withDuration: 3, delay: 0, options: opts, animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: {
self.playBtn.transform = CGAffineTransform(translationX: 0, y: 10)
})
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: {
self.playBtn.transform = CGAffineTransform.identity
})
}, completion: nil)
But really, it would be better if you learned how animation actually works before you get into this kind of thing. From your code, it appears to me you are just thrashing.

How to implement instagram similar like effect in ios? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I am developing a social app in which I want to implement like functionality similar to instagram, there are feeds with images similar to instagram when user double taps any image then it should show a heart icon with animation similar to instagram. I tried to do the same thing but unable to achieve the animation, can anybody tell me how can I do that.
I am attaching the image of instagram like functionality.
Here is an implementation:
- (void) animateLike {
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
heartPopup.transform = CGAffineTransformMakeScale(1.3, 1.3);
heartPopup.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1f delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
heartPopup.transform = CGAffineTransformMakeScale(1.0, 1.0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
heartPopup.transform = CGAffineTransformMakeScale(1.3, 1.3);
heartPopup.alpha = 0.0;
} completion:^(BOOL finished) {
heartPopup.transform = CGAffineTransformMakeScale(1.0, 1.0);
}];
}];
}];
}
Code For Swift 3.0
func likeAnimation() {
UIView.animate(withDuration: 0.3, delay: 0, options: .allowUserInteraction, animations: {() -> Void in
heartPopup.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
heartPopup.alpha = 1.0
}, completion: {(_ finished: Bool) -> Void in
UIView.animate(withDuration: 0.1, delay: 0, options: .allowUserInteraction, animations: {() -> Void in
heartPopup.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
}, completion: {(_ finished: Bool) -> Void in
UIView.animate(withDuration: 0.3, delay: 0, options: .allowUserInteraction, animations: {() -> Void in
heartPopup.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
heartPopup.alpha = 0.0
}, completion: {(_ finished: Bool) -> Void in
heartPopup.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
})
})
})
}
heartPopup is a UIImageView, set it up in the interface builder in the center of the image and set alpha to zero on it. Call the above method to animate the like effect.
Swift 4 (code from comment)
if let bigLikeImageV = likeImageV, liked == true {
UIView.animate(withDuration: 0.6, delay: 0, usingSpringWithDamping: 0.4, initialSpringVelocity: 0.2, options: .allowUserInteraction, animations: {
bigLikeImageV.transform = CGAffineTransform(scaleX: 1.6, y: 1.6)
bigLikeImageV.alpha = 1.0
}) { finished in
bigLikeImageV.alpha = 0.0
bigLikeImageV.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
}
}
Create a subclass (HEARTShapedView) of UIView, which contains the just the heart-shape drawn as a UIBezierPath, added to a CAShapedLayer, and animate it with CABasicAnimation during the layoutSubviews. Then, when animation is completed, remove heart shaped view (self) from it's superview.
To use it in your tableview, add it as a subview to your tableview cell, or image view, and the view should animate and remove it self after completion.

Resources