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)
}
Related
I have a scrollView and there is a textView inside it and there is a function that slide my scrollView(with animation) in my main vc also I have a button(inside the black circle) ,when I press it, my pop up viewcontroller opens then I choose a value for animation delay in my function.
When I press my play button (inside the red circle) , I want to dismiss my pop up vc and I want my function to run. See:
func startScrollSlideShow(sliderValue: Float) {
if (scrollView.contentOffset.y <= (scrollView.contentSize.height - scrollView.frame.size.height)){
//reach bottom
UIScrollView.animate(withDuration: TimeInterval(sliderValue), delay: 0.5, options: .allowAnimatedContent, animations: {
self.scrollView.contentOffset.y += 3.5
}) { (completion) in
self.startScrollSlideShow(sliderValue: Float(UserDefaults.standard.string(forKey: "sliderValue")!)!)
}
} else {
return
}
}
#objc func scrollTextView(){
self.present(SliderViewController(title: "Otomatik Kaydırma"), animated: true, completion: nil)
// self.startScrollSlideShow(sliderValue: Float(UserDefaults.standard.string(forKey: "sliderValue")!)!)
}
these are in my main vc not my pop up vc.
You can use the delegate pattern for this:
protocol PlayViewDelegate: class {
func playButtonPressed()
}
// Implement the protocol in your Main VC
extension MainViewController: PlayViewDelegate {
func playButtonPressed() {
// Play
}
}
// Add delegate to the alert like VC
class PlayViewController: UIViewController {
weak var delegate: PlayViewDelegate?
#IBAction
func playPressed() {
self.delegate?.playButtonPressed()
self.dismiss(animated: true, completion: nil)
}
}
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)
})
}
}
I would like to be able to add a modal view in front of my table view, that is displayed relative to the view rather than relative to the table view (as shown in the photos)1. Also how do I prevent the user interacting with the table behind. I have included the code used to animate my view in also. Thanks in advance!
func newPersonAnimateIn() {
self.overlayView.transform = CGAffineTransform.identity
self.view.addSubview(overlayView)
overlayView.center = self.view.center
overlayView.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3)
overlayView.alpha = 0
UIView.animate(withDuration: 0.4) {
//self.visualEffectView.effect = self.effectHolder
self.overlayView.alpha = 1
self.overlayView.transform = CGAffineTransform.identity
}
personName.becomeFirstResponder()
}
func newPersonAnimateOut() {
self.view.endEditing(true)
UIView.animate(withDuration: 0.3, animations: {
self.overlayView.alpha = 0
self.overlayView.transform = CGAffineTransform.identity
}){(success:Bool) in
self.overlayView.removeFromSuperview()
}
personName.text = ""
}
#IBAction func addPerson(_ sender: UIBarButtonItem) {
newPersonAnimateIn()
}
#IBAction func continueButton(_ sender: Any) {
newPersonAnimateOut()
}
Maybe this would be enough:
self.tableView.isUserInteractionEnabled = false
or create another view under your modal view that covers full screen and set isUserInteractionEnabled = false
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)
}
}
}
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
})
}