withDuration is ignored during UIView.animate - ios

I'am trying to animate the opacity of a AVPlayerLayer when a button is tapped. Here is my function :
#IBAction func boutonTapped(_ sender: UIButton) {
if(paused){
UIView.animate(withDuration: 5.0, animations: {
self.avPlayerLayer.opacity = 1.0
}, completion: nil)
//avPlayer.play()
}else{
UIView.animate(withDuration: 5.0, animations: {
self.avPlayerLayer.opacity = 0
}, completion:nil)
//avPlayer.pause()
}
paused = !paused
}
An opacity animation is launched but it is very speed (about 0.5s). I tried to change the duration for 10s and the animation is the same
I tried to add self.view.layoutIfNeeded() inside the animation block with no effect.
Have you any idea ? Thanks !

Instead of animating the opacity of avPlayerLayer, try animating the alpha of the customView where you're adding avPlayerLayer, i.e.
#IBAction func boutonTapped(_ sender: UIButton) {
UIView.animate(withDuration: 5.0) {
self.customView.alpha = paused ? 1.0 : 0.0 //here...
paused ? self.avPlayer.play() : self.avPlayer.pause()
}
paused = !paused
}
There is no need to call self.view.layoutIfNeeded().

You should change an animation code to change opacity of AVPlayerLayer as follow:
#IBAction func boutonTapped(_ sender: UIButton) {
UIView.transition(with: self.videoPlayerView, duration: 5.0, options: [.transitionCrossDissolve], animations: {
self.videoPlayerView.layer.sublayers?.first(where: { $0 is AVPlayerLayer })?.opacity = paused ? 1 : 0
}, completion: nil)
paused ? avPlayer.play() : avPlayer.pause()
}
videoPlayerView is view where you have added AVPlayerLayer instance.

I think you need to put self.view.layoutIfNeeded() inside animation block but not the opacity update code. Like this,
#IBAction func boutonTapped(_ sender: UIButton) {
if (paused) {
self.avPlayerLayer.opacity = 1.0
//avPlayer.play()
} else {
self.avPlayerLayer.opacity = 0
//avPlayer.pause()
}
UIView.animate(withDuration: 5.0, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
paused = !paused
}

Related

After custom segue finishes camera turns off?

I am trying to use a custom transition to a full screen custom camera. When I do so using a slow fade animation it after completing the animation turns black.
The camera which at the beginning of the animation seems to work,
suddenly goes away leaving behind the black background.
How can I make the transition work correctly?
Code:
mainVC:
#objc func buttonUp(_ sender: UIButton) {
toCam.transform = CGAffineTransform.identity.scaledBy(x: 1, y: 1)
toCam.backgroundColor = .yellow
segue()
}
func segue() {
performSegue(withIdentifier: "GoToCam", sender: self)
}
Custom segue class:
class goToCamAnimCustom: UIStoryboardSegue {
override func perform() {
scale()
}
func scale() {
guard let destinationView = self.destination.view else {
// Fallback to no fading
self.source.present(self.destination, animated: false, completion: nil)
return
}
destinationView.alpha = 0
self.source.view?.addSubview(destinationView)
UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
destinationView.alpha = 0.5
}, completion: { _ in
self.source.present(self.destination, animated: false, completion: nil)
})
}
}

Animating UIView isHidden subviews

I have a UIView EmptyCollectionView, which I display when my UICollectionView is empty. The way I have this working is that I create the UIView and addSubview in viewDidLoad of my ViewController, then change toggle isHidden property of the view (as well as the collectionview) as needed.
I'd like to polish things up a little now I have the core function working, and I wan't to add some subtle animation to the subviews contained in my empty view, such as making the contained imageview bounce on display.
So my question is, what is the best way to detect when the UIView is being shown (i.e. is there a viewDidAppear type callback I could use)?
Supplementary question: I'm new to this... Is adding the empty view and toggling the isHidden property a good way of doing this? Or should I be doing it a different way? (i.e. should I instead be creating and destroying the view as needed, rather than keeping it around)
Thanks
The best way in my opinion is to extend UIView
extension UIView {
func fadeIn(_ duration: TimeInterval = 0.2, onCompletion: (() -> Void)? = nil) {
self.alpha = 0
self.isHidden = false
UIView.animate(withDuration: duration,
animations: { self.alpha = 1 },
completion: { (value: Bool) in
if let complete = onCompletion { complete() }
}
)
}
func fadeOut(_ duration: TimeInterval = 0.2, onCompletion: (() -> Void)? = nil) {
UIView.animate(withDuration: duration,
animations: { self.alpha = 0 },
completion: { (value: Bool) in
self.isHidden = true
if let complete = onCompletion { complete() }
}
)
}
}
So you just have to call view.fadeIn() for a default 0.2 sec animation, or view.fadeIn(1) to make it last one second.
You can even add a completion event:
view.fadeOut(0.5, onCompletion: {
print("Animation completed, do whatever you want")
})
This works, I hope it can help you. To hide view:
UIView.animate(withDuration: 0.3/*Animation Duration second*/, animations: {
self.EmptyCollectionView.alpha = 0
}, completion: {
(value: Bool) in
self.EmptyCollectionView.isHidden = true
})
To show view:
self.EmptyCollectionView.isHidden = false
UIView.animate(withDuration: 0.3, animations: {
self.EmptyCollectionView.alpha = 1
}, completion: nil)
Swift 4.2 extension to allow animation when setting isHidden on any UIView class:
extension UIView {
func setIsHidden(_ hidden: Bool, animated: Bool) {
if animated {
if self.isHidden && !hidden {
self.alpha = 0.0
self.isHidden = false
}
UIView.animate(withDuration: 0.25, animations: {
self.alpha = hidden ? 0.0 : 1.0
}) { (complete) in
self.isHidden = hidden
}
} else {
self.isHidden = hidden
}
}
}
You can animate the alpha property of EmptyCollectionView to either 0 to hide or 1 to show
UIView.animate(withDuration: 0.5) {
self.EmptyCollectionView.alpha = 0
}
Also make sure that isOpaque property is set to False to enable Transparency of the view
Swift 5
import UIKit
extension UIView {
func animateSetHidden(_ hidden: Bool, duration: CGFloat = CATransaction.animationDuration(), completion: #escaping (Bool)->() = { _ in}) {
if duration > 0 {
if self.isHidden && !hidden {
self.alpha = 0
self.isHidden = false
}
UIView.animate(withDuration: duration, delay:0, options: .beginFromCurrentState) {
self.alpha = hidden ? 0 : 1
} completion: { c in
if c {
self.isHidden = hidden
}
completion(c)
}
} else {
self.isHidden = hidden
self.alpha = hidden ? 0 : 1
completion(true)
}
}
}

Button won't unhide

I can get my buttons to hide, but not unhide.
I hide the answerOneCover button on tap with:
#IBAction func answerOneCoverTapped(_ sender: Any) {
animateButtonCoverOut(button: answerOneCover)
}
func animateButtonCoverOut(button: UIButton) {
UIView.animate(withDuration: 1.0, delay: 0.1, options:
UIViewAnimationOptions.curveEaseOut, animations: {
button.alpha = 0
}, completion: { finished in
button.isHidden = true
})
}
And I try to unhide the answerOneCover button when a different button, answerOneButtonText button is tapped:
#IBAction func answerOneButtonTextTapped(_ sender: Any) {
answerOneCover.isHidden = false
}
But I can't get answerOneCover to unhide. Is there any way to do this that I'm missing?
You have to set the buttons Alpha back to 1. change your code to look like this:
#IBAction func answerOneButtonTextTapped(_ sender: Any) {
answerOneCover.alpha = 1
answerOneCover.isHidden = false
}
OR you can put it in your animations completion like so:
func animateButtonCoverOut(button: UIButton) {
UIView.animate(withDuration: 1.0, delay: 0.1, options:
UIViewAnimationOptions.curveEaseOut, animations: {
button.alpha = 0
}, completion: { finished in
button.isHidden = true
button.alpha = 1
})
}

Animated display button

I'm trying to create a basic animation. I need to touch on a button to hide or show.
I wrote this code to tap on the screen:
func visibleControlButton(_ sender: UITapGestureRecognizer) {
if (backButton!.isHidden) {
_UIButtonHiddenAnimation.hiddenAnimation(button: self.backButton!, hide: false)
} else {
_UIButtonHiddenAnimation.hiddenAnimation(button: self.backButton!, hide: true)
}
}
Definition _UIButtonHiddenAnimation:
class _UIButtonHiddenAnimation {
class func hiddenAnimation(button: UIButton, hide: Bool) {
UIView.animate(withDuration: 0.2,
animations: {
hide ? (button.alpha = 0) : (button.alpha = 1.0)
},
completion: {
finished in hide ? (button.isHidden = true) : (button.isHidden = false)
})
}
}
Animates just hide the button. How to make an animated appearance of a button?
The problem is that if the button is hidden, you are animating the alpha to 1 but we cannot see that — because the button is hidden! Then you set isHidden to false and the button jumps into view.
The solution: forget all about isHidden and change only the alpha — and then change your if test to match what you are doing with the button, i.e. simply test against its alpha value. Thus (neatening things up as we go):
class _UIButtonHiddenAnimation {
class func hiddenAnimation(button: UIButton, hide: Bool) {
UIView.animate(withDuration: 0.2, animations: {
button.alpha = hide ? 0 : 1.0
})
}
}
func visibleControlButton(_ sender: UITapGestureRecognizer) {
_UIButtonHiddenAnimation.hiddenAnimation(
button: self.backButton!, hide: backButton!.alpha > 0.1)
}

UIView is not aminating for the first time

I am trying to animate a UIView on button click.
It does appear on first click but only after that.
#IBAction func viewDetails(sender: AnyObject) {
UIView.animateWithDuration(0.5 as NSTimeInterval, animations: {
println(self.viewDetailsView.center.x)
println(self.viewDetailsView.hidden)
self.viewDetailsView.hidden = false
self.viewDetailsView.center = CGPointMake(self.viewDetailsView.center.x - 4000, self.viewDetailsView.center.y)
self.view.layoutIfNeeded()
}, completion: {
finished in
self.detailsVisible = true
}) }
Trying this:
#IBAction func viewDetails(sender: AnyObject) {
println(self.viewDetailsView.center.x)
println(self.viewDetailsView.hidden)
self.viewDetailsView.hidden = false
self.viewDetailsView.center = CGPointMake(self.viewDetailsView.center.x - 4000, self.viewDetailsView.center.y)
UIView.animateWithDuration(0.5 as NSTimeInterval, animations: {
self.view.layoutIfNeeded()
}, completion: { finished in
self.detailsVisible = true
})
}

Resources