I have a little annoying problem. I have a CATextLayer, which I use to display the placeholder of UITextView. The fact is that when animating this layer, its velocity is too small and I see "jumps" during the animation. I use UIView.animate with a velocity parameter, but it ignores it.
GIF FILE:
DispatchQueue.main.async {
UIView.animate(
withDuration: 0.2,
delay: 0.0,
usingSpringWithDamping: 1.0,
initialSpringVelocity: 1.0, // Ignore any options
options: .curveEaseOut,
animations: {
self.floatingLabel?.fontSize = 10
self.floatingLabel?.frame = self.toggledFloaterFrame
})
}
What could be the problem?
Animation of the fontSize property is not possible. Try using the transform to scale it down.
You can use CGAffineTransform(scaleX: scale, y: scale) with scale being 10/self.floatingLabel.fontSize and CGAffineTransform.identity to go back to full size.
Related
I have imageView like vinyl record. And I want to create rotate animation. But if I use this code my vinyl record not exactly rotate around center. In this animation my image a little bit shifts up and down. How to fix it?
func startRotateView(targetView: UIView, duration: Double = 3.0) {
UIView.animate(withDuration: duration, delay: 0.0, options: .curveLinear, animations: {
targetView.transform = targetView.transform.rotated(by: CGFloat(Double.pi))
}) { finished in
self.startRotateView(targetView: targetView, duration: duration)
}
}
Use CGAffineTransform instead of rotated
targetView.transform = CGAffineTransform(rotationAngle: .pi)
I am trying to implement following animation for my application onboarding and it needs to be play forever and reverse back every time it finishes.
I designed following image to accomplish that animation.
The image size is 880x335. So I wrote following code to animate the image.
func startAnimation(with duration: TimeInterval, afterDelay time: TimeInterval, horizontalConstantFirstPosition: CGFloat, horizontalConstantSecondPosition: CGFloat) {
switch animationOrder {
case .first:
self.animatedImageViewAnimatableConstraint.constant = 110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .second
})
case .second:
self.animatedImageViewAnimatableConstraint.constant = -110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .third
})
case .third:
self.animatedImageViewAnimatableConstraint.constant = -330
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .fourth
})
case .fourth:
self.animatedImageViewAnimatableConstraint.constant = 110
UIView.animate(withDuration: duration, delay: time, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
self.animationOrder = .second
})
}
}
Basically, animatedImageViewAnimatableConstraint is the center X constraint that is initialized with 330 which is the position of first image I designed. Every time my animation method is called I changed center x anchor to the positions of value 330, 110, -110, -330 and so on.
However, when I applied it is not animating as expected. It returns back from fourth portion of the image to first one, it is excepted to go from fourth position to second one as shown above.
What should I do for the correct one, or which part is looking like wrong? Thanks in advance.
#IBOutlet weak var imageView: UIImageView!
let images = [#imageLiteral(resourceName: "img1"), #imageLiteral(resourceName: "img2"), #imageLiteral(resourceName: "img3")]
imageView.animationImages = images
imageView.animationDuration = 3.0 //1 sec for each image
imageView.animationRepeatCount = 0 //Set 0 for infinite
imageView.startAnimating()
To stop just call
imageView.stopAnimating()
I am trying to figure out why UIView.animate does not work as intended.
I know with UIView.animateKeyframes I can chain multiple types of animations together, but in this instance I am doing just one animation transform from the current size to 0.0.
The spinner image is already spinning using CABasicAnimation prior to this transform using:
let spinAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
spinAnimation.toValue = .pi * 2.0 // 360ยบ spin
spinAnimation.duration = 1.4
spinAnimation.repeatCount = Float.greatestFiniteMagnitude // Repeat forever in loops.
spinAnimation.isCumulative = true
spinAnimation.isRemovedOnCompletion = false
self.spinnerImageView.layer.add(spinAnimation, forKey: self.spinnerAnimationKey)
UIView KeyFrame Animation
UIView.animateKeyframes(withDuration: Constants.AnimationDuration.standard, delay: 0.0, options: .calculationModeLinear, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.4, animations: {
self.spinner.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
})
}) { (_) in
super.endRefreshing()
}
UIView Animation
UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveLinear, animations: {
self.spinner.transform = CGAffineTransform(scaleX: 0.0, y: 0.0)
}) { (_) in
super.endRefreshing()
}
The keyframe animation works as intended where it shows the animating image shrink to 0.0, but the standard animate just causes the image to disappear. Shouldn't they act in the same way or is it because the image already has a CABasicAnimation layer that is causing the animate to not work properly? I would prefer to use .animate since I am only doing a transformation.
I want to change the button's scale and add a shadow effect when the button is clicked, but the added shadow effect is not complete, where is the problem, why is the shadow of the last button only complete?
#objc func ButtonOnClicking(_ sender:homePageBtn){
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.5, options: UIViewAnimationOptions.allowAnimatedContent, animations: {
sender.layer.masksToBounds = false
sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
sender.layer.shadowColor = ColorHellp.getColor("333333").cgColor
sender.layer.shadowOffset = CGSize(width: 0, height: 0)
sender.layer.shadowRadius = 4
sender.layer.shadowOpacity = 0.3
}) { (isfinished) in
print("finished")
}
}
I can see, that also for the first button the shadow is complete, but it looks like, that the button is under the other ones.
So try something like bringSubViewToFront or change the z-index.
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.