I did that...
ivImageLoadingInside.center = CGPoint(x: 25, y: 0)
UIView.animate(withDuration: 2, delay: 0, options: .repeat, animations: {
self.ivImageLoadingInside.center = CGPoint(x: 80, y: 0)
}, completion: nil)
But always stops in the middle.
Here is the image with the animation
private func animation(viewAnimation: UIView) {
UIView.animate(withDuration: 2, animations: {
viewAnimation.frame.origin.x = +viewAnimation.frame.width
}) { (_) in
UIView.animate(withDuration: 2, delay: 1, options: [.curveEaseIn], animations: {
viewAnimation.frame.origin.x -= viewAnimation.frame.width
})
}
}
self.ivImageLoadingInside.center = CGPoint(x: 80 - self.ivImageLoadingInside.bounds.width / 2, y: 0)
I got it! You have to put the constraints and do this...
if animate {
ivImageLoadingInside.frame = CGRect(x: 0 - 160, y: 123, width: 160, height: 12)
UIView.animate(withDuration: 1.2, delay: 0, options: .repeat, animations: {
self.ivImageLoadingInside.frame = CGRect(x: ScreenSize.SCREEN_WIDTH, y: 123, width: 160, height: 12)
}, completion: nil)
} else {
ivImageLoadingInside.layer.removeAllAnimations()
}*
Look at this link http://mathewsanders.com/prototyping-iOS-iPhone-iPad-animations-in-swift/
Related
I have a UIImageView.
I can either get it bouncing by using animate:
self.myImage.frame = CGRect(x: myImage.center.x, y: myImage.center.y, width: 50, height: 70)
UIView.animate(withDuration: 0.4, delay: 0, options: [.repeat, .autoreverse] , animations: {
self.myImage.frame = CGRect(x: self.myImage.center.x, y: self.myImage.center.y, width: 70, height: 80);
}) { (completed) in }
or, I can drag it by using panGestureRecogniser:
#IBAction func dragView(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
if let viewToDrag = sender.view {
viewToDrag.center = CGPoint(x: viewToDrag.center.x + translation.x, y: viewToDrag.center.y + translation.y)
sender.setTranslation(.zero, in: viewToDrag)
}
How do I switch from first bouncing and then to dragging?
Add .allowUserInteraction to your options when setting up the animation
self.myImage.frame = CGRect(x: myImage.center.x, y: myImage.center.y, width: 50, height: 70)
UIView.animate(withDuration: 0.4, delay: 0, options: [.repeat, .autoreverse, .allowUserInteraction] , animations: {
self.myImage.frame = CGRect(x: self.myImage.center.x, y: self.myImage.center.y, width: 70, height: 80);
}) { (completed) in }
EDIT:
to break the bouncing animation loop use self.myImage.layer.removeAllAnimations() in the beginning state of the pan gesture like so:
#IBAction func dragView(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
if let viewToDrag = sender.view {
if sender.state == .began {
viewToDrag.layer.removeAllAnimations()
}
viewToDrag.center = CGPoint(x: viewToDrag.center.x + translation.x, y: viewToDrag.center.y + translation.y)
sender.setTranslation(.zero, in: viewToDrag)
}
I want to make an animation that move a background image from right to left than left to right.
I use this code but not works
UIView.animate(withDuration: 5, delay: 0, options: .repeat ,animations: { () -> Void in
imageView.transform = CGAffineTransform(translationX: -imageView.frame.width + self.view.bounds.width, y: 0)
UIView.animate(withDuration: 5, delay: 1, options: .repeat ,animations: { () -> Void in
imageView.transform = CGAffineTransform(translationX: +imageView.frame.width - self.view.bounds.width, y: 0)
})
})
I solved with this
UIView.animate(withDuration: 30.0, delay: 0, options: [.repeat, .autoreverse], animations: {
imageView.transform = CGAffineTransform(translationX: -imageView.frame.width + self.view.bounds.width, y: 0)
}, completion: nil)
Use the following code if you want to use the legacy animate(withDuration:animations:) API. However, you need to wait for the first animation to be finished - this means you have to use the completion block.
However, your value for translationX does not makes sense as well.
UIView.animate(withDuration: 1, animations: {
self.imageView.transform = CGAffineTransform(translationX: -self.imageView.frame.width, y: 0)
}) { _ in
UIView.animate(withDuration: 1) {
self.imageView.transform = CGAffineTransform.identity
}
}
I would strongly recommend having a look at the "new" way of doing Animations: UIViewPropertyAnimator(https://developer.apple.com/documentation/uikit/uiviewpropertyanimator)
I would like to animate the whole chain for forever.
UIView.animate(withDuration: 2.0, delay: 0.2, options: .curveEaseOut, animations: {
self.circleImageView.transform = CGAffineTransform(scaleX: 9, y: 9)
}) { (_) in
UIView.animate(withDuration: 2.0, delay: 0.2, options: .curveEaseIn, animations: {
self.circleImageView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
}, completion: nil)
}
You can wrap the two animations within a keyframe animation. Then you can .repeat that:
UIView.animateKeyframes(withDuration: 4.4, delay: 0, options: .repeat, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 2.0/4.4) {
self.circleImageView.transform = .init(scaleX: 9, y: 9)
}
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 2.0/4.4) {
self.circleImageView.transform = .init(scaleX: 0.01, y: 0.01)
}
})
Wrap it up inside a method:
func repeatingAnimation() {
UIView.animate(withDuration: 2.0, delay: 0.2, options: .curveEaseOut, animations: {
self.circleImageView.transform = CGAffineTransform(scaleX: 9, y: 9)
}) { (_) in
UIView.animate(withDuration: 2.0, delay: 0.2, options: .curveEaseIn, animations: {
self.circleImageView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
}, completion: { [weak self] _ in
self?.repeatingAnimation()
})
}
}
I have a view which I am animating in such a way that it expands and moves to a new set of coordinates in the View Controller. I am doing this using Keyframes:
UIView.animateKeyframesWithDuration(0.5, delay: 0, options: .CalculationModeCubic, animations: {
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.5) {
//Moving main View
tappedView.frame = CGRectMake((self.screenSize.width/2)-250, (self.screenSize.height/2)-250, 500, 500)
}
}, completion: nil)
The problem is that once the animation is completed, the view returns to its original position and size.
Is there a way to prevent this from happening in Swift?
This is an issue if one is using auto layout. In which case, the final coordinates must be put in the completion handler for it to work.
Swift 2
UIView.animateKeyframesWithDuration(0.5, delay: 0, options: .CalculationModeCubic, animations: {
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.5) {
// Moving main View
tappedView.frame = CGRectMake((self.screenSize.width/2)-250, (self.screenSize.height/2)-250, 500, 500)
}
}, completion: {(finished: Bool) -> Void in
tappedView.frame = CGRectMake((self.screenSize.width/2)-250, (self.screenSize.height/2)-250, 500, 500)
})
Swift 3, 4, 5
UIView.animateKeyframes(withDuration: 0.5, delay: 0, options: .calculationModeCubic, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.5) {
// Moving main View
tappedView.frame = CGRect(x: (self.screenSize.width/2)-250, y: (self.screenSize.height/2)-250, width: 500, height: 500)
}
}, completion: {(finished: Bool) -> Void in
tappedView.frame = CGRect(x: (self.screenSize.width/2)-250, y: (self.screenSize.height/2)-250, width: 500, height: 500)
})
I have 2 animations that get triggered by pressing 2 different buttons. How can I determine which one I see first when they are literally occupying the same space and are on top of each other. Is there some code I can use to determine the hierarchy of what UIImageView is shown first?
Here is an example of what I am dealing with. I have a "lightning" image and a cloud image.
//Lightning
#IBAction func lightningOne(sender: UIButton) {
self.darkCloud.hidden = false
let lightning = UIImageView()
lightning.image = UIImage(named: "lightning")
lightning.frame = CGRect(x:-41, y:29, width:30, height:105)
self.view.addSubview(lightning)
let options = UIViewAnimationOptions.CurveEaseIn
UIView.animateWithDuration(0.1, delay: 0.5, options: options, animations: {
lightning.frame = CGRect(x: -45, y: 34, width: 30, height: 105)
}, completion: { animationFinished in
self.darkCloud.hidden = false
UIView.animateWithDuration(0.0, delay: 0.0, options: options, animations: {
self.view.addSubview(lightning)
lightning.frame = CGRect(x: 41, y: 34, width: 30, height: 105)
}, completion: { animationFinished in
self.darkCloud.hidden = false
UIView.animateWithDuration(0.7, delay: 0.0, options: options, animations: {
self.view.addSubview(lightning)
lightning.frame = CGRect(x: 41, y: 35, width: 30, height: 105)
}, completion: { animationFinished in
lightning.removeFromSuperview()
self.darkCloud.hidden = true
})
})
})
}
Here is the code I use to show the cloud.
// Clouds
func movingClouds() {
let options = UIViewAnimationOptions.Repeat
let cloud = UIImageView()
cloud.image = UIImage(named: "cloud1")
cloud.frame = CGRect(x: -80, y: 110, width: 78, height: 42)
self.view.addSubview(cloud)
UIView.animateWithDuration(140.0, delay: 0.0, options: options, animations: {
cloud.frame = CGRect(x: 350, y: 110, width: 78, height: 42)
}, completion: nil)
}
How can I make sure the lightning image shows up behind the cloud when I trigger it and they happen to cross each other?