Fading in/out a UILabel - ios

My stackview contains 2 labels. I want to animate the hiding process like giving it a fade out animation when one of the labels is hidden or a fade in animation when one of the labels is unhidden. How would I do this?

You should animate the alpha of the label.
UIView.animate(withDuration: 1, animations: {
disclaimerLabel.alpha = 0
}

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
la1.layer.add(flash, forKey: nil)

Related

Animating SCNCamera.fStop with property key path doesn't work, only inside implicit SCNTransaction

This code strangely doesn't animate the fStop:
cameraNode.camera!.wantsDepthOfField = true
cameraNode.camera!.focusDistance = 2
let animation = CABasicAnimation(keyPath: "fStop")
animation.toValue = 0.5
animation.duration = 0.3
cameraNode.camera!.addAnimation(animation, forKey: nil)
while this one does:
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.3
cameraNode.camera!.fStop = 0.5
SCNTransaction.commit()
Why?
The animation gets removed on completion so the fStop is reset to its initial value. You just need to set the final value on it when you start the animation.
let animation = CABasicAnimation(keyPath: "fStop")
animation.fromValue = cameraNode.camera!.fStop
animation.toValue = 0.5
animation.duration = 0.3
cameraNode.camera!.addAnimation(animation, forKey: nil)
cameraNode.camera!.fStop = 0.5

Animate shadow properties

I want to animate shadow properties for a view. Initially I tried:
func animateIn(delay: TimeInterval = 0) {
UIView.animate(withDuration: 0.2, delay: delay, options: .allowUserInteraction, animations: {
self.shadowView.layer.shadowColor = UIColor.black.cgColor
self.shadowView.layer.shadowOffset = CGSize(width: 15, height: 15)
self.shadowView.layer.shadowRadius = 20
self.shadowView.layer.shadowOpacity = 0.2
self.layoutIfNeeded()
}, completion: nil)
}
which doesnt work given that UIView.animate doesnt work with layers.
I tested the following post (How to animate layer shadowOpacity?), but it only specifies how to animate the shadow Opacity. Is there any way to animate all my shadow properties like I would with an animation blocl?
You are very close, you just create multiple CABasicAnimations for all the property changes and then you can use CAAnimationGroup
So let say you have 2 CABasicAnimation animations like:
let shadownOpacityAnimation = CABasicAnimation(keyPath: "shadowOpacity")
...
let shadowRadiusAnimation = CABasicAnimation(keyPath: "shadowRadius")
...
Then you can add them using CAAnimationGroup
let group = CAAnimationGroup()
group.duration = 0.2
group.repeatCount = 1
group.autoreverses = false
group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
group.animations = [shadownOpacityAnimation, shadowRadiusAnimation]
layer.add(group, forKey: "allAnimations")
You can read more about it in this answer:
How can I create an CABasicAnimation for multiple properties?

How rotate .transitionCurlDown animation?

How rotate .transitionCurlDown animation to get the rotation of the book sheet (horizontal, not vertical), same as this:
There is vertical page curl animation:
UIView.transition(with: self.myView, duration: 0.7,
options: .transitionCurlDown, animations: {
})
Important: I don't want to use transition between UIViewControllers or UIPageControllers, I want to apply animation on UIView on the current screen.
Solution:
func animatePage(side: PageCurl, textView: UITextView) {
UIView.animate(withDuration: 0.3, animations: {
let animation = CATransition()
animation.duration = 0.3
animation.startProgress = 0.0
animation.endProgress = 1
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
animation.type = CATransitionType(rawValue: "pageCurl")
if side == .left {
animation.subtype = CATransitionSubtype(rawValue: "fromLeft")
} else {
animation.subtype = CATransitionSubtype(rawValue: "fromRight")
}
animation.isRemovedOnCompletion = false
animation.isRemovedOnCompletion = false
textView.layer.add(animation, forKey: "pageFlipAnimation")
})
}
Use:
animatePage(side: .left, textView: myTextView)
Just one note to the accepted answer. If you want to use it like book flip animation, change your imageView.image from cover to page, for example, before this line animatePage(side: .left, textView: myTextView)
So if you have cover image and page image, your code should be like:
imageView.image = UIImage(named: "page.png")
animatePage(side: .right, view: imageView)
And it will give your a nice looking flip animation from cover to page

Swift Change circular border color with animation

I created a circular button using swift, what I am trying to do is changing the border color with animation
I used the following code :
let color = CABasicAnimation(keyPath: "borderColor")
color.fromValue = UIColor.black.cgColor
color.toValue = UIColor.red.cgColor
color.duration = 1
color.repeatCount = 1
sender.layer.add(color, forKey: "color and width")
The border color is changing but it is not given the desire effect, it change the border color all at once. What I would like to have as effect is like your drawing over the old color, to keep it simple ==> like a progress bar where u see the old color like fade away and be replaced by the new color.
Is there is any way to do that?
Thanks for helping.
Updating code
var storkeLayer = CAShapeLayer()
#IBOutlet weak var Mybut: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
storkeLayer.fillColor = UIColor.clear.cgColor
storkeLayer.strokeColor = UIColor.black.cgColor
storkeLayer.lineWidth = 2
// Create a rounded rect path using button's bounds.
storkeLayer.path = CGPath.init(roundedRect: Mybut.bounds, cornerWidth: Mybut.frame.width / 2 , cornerHeight: Mybut.frame.height / 2, transform: nil)
// Add layer to the button
Mybut.layer.addSublayer(storkeLayer)
}
#IBAction func bytton(_ sender: UIButton) {
storkeLayer.fillColor = UIColor.clear.cgColor
storkeLayer.strokeColor = UIColor.red.cgColor
storkeLayer.lineWidth = 2
// Create a rounded rect path using button's bounds.
storkeLayer.path = CGPath.init(roundedRect: Mybut.bounds, cornerWidth: Mybut.frame.width / 2 , cornerHeight: Mybut.frame.height / 2, transform: nil)
// Add layer to the button
sender.layer.addSublayer(storkeLayer)
// Create animation layer and add it to the stroke layer.
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = CGFloat(0.0)
animation.toValue = CGFloat(1.0)
animation.duration = 1
animation.fillMode = kCAFillModeForwards
// animation.fillMode = kCAFillModeBackwards
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
storkeLayer.add(animation, forKey: "circleAnimation")
}
You can stroke the button's path using the following code snippet.
#IBAction func buttonTapped(_ sender: UIButton) {
let storkeLayer = CAShapeLayer()
storkeLayer.fillColor = UIColor.clear.cgColor
storkeLayer.strokeColor = UIColor.red.cgColor
storkeLayer.lineWidth = 2
// Create a rounded rect path using button's bounds.
storkeLayer.path = CGPath.init(roundedRect: sender.bounds, cornerWidth: 5, cornerHeight: 5, transform: nil) // same path like the empty one ...
// Add layer to the button
sender.layer.addSublayer(storkeLayer)
// Create animation layer and add it to the stroke layer.
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = CGFloat(0.0)
animation.toValue = CGFloat(1.0)
animation.duration = 1
animation.fillMode = kCAFillModeForwards
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
storkeLayer.add(animation, forKey: "circleAnimation")
}
This snippet creates something like this:

Flipping x animation with repetition after a certain duration

I was trying to do a "flip x animation" for a UIButton. I have seen some documentation on how to do this animation but i couldn't find how to do it with repetition. For example, i want to flip the image of the UIButton and change it after a time interval of 5 sec with repetition.
Any help? Thanks.
You can use CAAnimationGroup to group an array of animations. Total animation for whole animationGroup is 6.0, flip animation takes place for 1.0 second. so remaining 5.0 seconds act as delay here.
EDIT: CATransaction.setCompletionBlock can be used but it will only call completion after all animations are completed. So now the flip will occur only for one time and on completion you will receive completion call, and update image view and initiate flip animation again.
Like this
imageView.flip {
// update imageView and call it again.
}
extension UIView {
func flip(completion: #escaping ()->()) {
CATransaction.begin()
CATransaction.setCompletionBlock {
// completion code here
completion()
}
let animationGroup = CAAnimationGroup()
animationGroup.duration = 6.0
animationGroup.repeatCount = 1
let easeInOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let animation = CABasicAnimation(keyPath: "transform")
animation.duration = 1.0
animation.autoreverses = true
animation.fromValue = CATransform3DIdentity
animation.toValue = NSValue(caTransform3D: CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0))
animation.timingFunction = easeInOut
animationGroup.animations = [animation]
layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
layer.add(animationGroup, forKey: "flip")
CATransaction.commit()
}
}

Resources