I am trying to fade-in a background gradient image and slide up a uiview card from the bottom (off-screen) to the center of the uiviewcontroller - executing both animations simultaneously when the uiviewcontroller is presented modally.
What I've attempted is to set the uiviewcontroller modal transition style to cross dissolve, which would provide the fade-in effect for the background gradient image, and in viewDidAppear run the animation to slide up the uiview card from the bottom to center.
While this works, there's a slight delay with the card, and ideally I hoped both animations took place at the same time.
Is this grouping possible? Any guidance would be appreciated.
Below is relevant code in the modally presented view controller:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
alertViewCenterYConstraint.constant += view.bounds.height
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.1, delay: 0, options: .curveEaseOut, animations: {
self.alertViewCenterYConstraint.constant = 0
self.view.layoutIfNeeded()
}, completion: nil)
}
This one works like a magic. I love it.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
alertViewCenterYConstraint.constant += view.bounds.height
DispatchQueue.main.async {
UIView.animate(withDuration: 0.1, delay: 0.05, options: .curveEaseOut, animations: {
self.alertViewCenterYConstraint.constant = 0
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Related
I am trying to make a side menu which reacts to a hamburger icon clicked.
I created another storyboard with a ViewConroller which contains the TableView in it.
I created a ViewController for this storyboard ViewController.
In the First ViewController (which is not a container), I have the following code:
var menuVC: UIViewController!
var isExpanded = false
#IBAction func MenuTapped(_ sender: UIButton) {
isExpanded = !isExpanded
showMenuVC(shouldExpand: isExpanded)
}
func showMenuVC(shouldExpand: Bool) {
if shouldExpand {
// show menu
if menuVC == nil {
print ("ONLY ONCE")
let storyboard = UIStoryboard(name: "Menu", bundle: .main)
menuVC = storyboard.instantiateViewController(withIdentifier: "MenuSB") as! MenuVC
menuVC.view.frame = self.view.frame.offsetBy(dx: view.frame.width, dy: 0)
menuVC.willMove(toParent: self)
self.view.insertSubview(menuVC.view, at: 0)
self.addChild(menuVC)
menuVC.didMove(toParent: self)
}
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.view.frame.origin.x = 80 - self.view.frame.width
}, completion: nil)
} else {
// hide menu
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.view.frame.origin.x = 0
}, completion: nil)
}
}
The thing is, the TableView is not responding to anything. Not scrolling, not clicking. I also tried a UIButton and it is not clickable.
The problem is, that the first ViewController is active while the MenuVC is not.
It is important to have both of them active, since the hamburger icon in the first ViewController closes the menu, but I need the MenuVC to be active as well.
Any thoughts?
Try to replace this line:
self.view.insertSubview(menuVC.view, at: 0)
with this:
self.view.addSubview(menuVC.view)
since I have no idea about the subviews you have in self.view, because there might be some views on top of your menu which have isUserInteractionEnabled set to true
this may seem obvious to some of you but I can't find an answer anywhere online. I am trying to make my Navigation Bar only appear on one View Controller so as all the tutorials show I just added this:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: false)
}
But when I exit out of this View Controller and then return to it, the Nav Bar isnt there. Any ideas??
I think you're on the right track however you need to define the action taken. Let's say you have UIScrollView in the View Controller and you want the navigation bar to disappear so here's the code the best you can use.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if(velocity.y>0) {
UIView.animate(withDuration: 2.5, delay: 0, options: UIViewAnimationOptions(), animations: {
self.navigationController?.setNavigationBarHidden(true, animated: true)
}, completion: nil)
} else {
UIView.animate(withDuration: 2.5, delay: 0, options: UIViewAnimationOptions(), animations: {
self.navigationController?.setNavigationBarHidden(false, animated: true)
}, completion: nil)
}
}
In your case you don't need to declare the animation twice it's already defined by the function try removing that as following.
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: false)
}
I am a new Swift writer who is looking for an answer to a relatively specific question. Please forgive any novice mistakes.
I am trying to create a Pop Up on the screen programmatically that layers two view controllers so that one view controller is visible on the other, with a level of opacity that makes the background visible.
After a transition from my GameViewController see here:
let gameOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "gameOverID") as! GameOverViewController
self.addChildViewController(gameOverVC)
gameOverVC.view.frame = self.view.frame
self.view.addSubview(gameOverVC.view)
gameOverVC.didMove(toParentViewController: self)
}
... I instantiate a ViewController of GameOverViewController to fit over the GameViewController. After that I go to my GameOverViewController class and attempt to set the background color to be opaque with the following line of code:
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.8)
The problem is that I end up with is a background that is not opaque, when in reality I would rather the GameViewController to layer on top of the GameViewController with an opaque background to still be able to see the Game.
I also animate with the following within my GameOverViewController:
func showAnimate()
{
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0
UIView.animate(withDuration: 0.25, animations: {
self.view.alpha = 1.0
self.view.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
})
}
func removeAnimate()
{
UIView.animate(withDuration: 0.25, animations: {
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0
}, completion: { (finished: Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
})
}
I'm not sure what is the source of my problem is.
Thank you for your help.
change background color of game over view Controller in interface builder like this
Also , take note of that you remove the game viewController's view in this line in removeAnimate func
self.view.removeFromSuperview()
this may cause black background if you do it before showing game over VC
for the view that sits on top, use: overFullScreen and then simply present it.
let topVC = topVC()
topVC.modalPresentationStyle = .overFullScreen
self.present(VCTobePresented, animated: true, completion: nil)
I have a UIViewController VC1 that contains a UIImageView loadingImg. When you segue from a previous UIViewController VC0, it animates. Here is some code from VC1:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
func animate() {
UIView.animate(withDuration: 1, delay: 0, options: [.repeat, .curveLinear], animations: {
self.loadingImg.transform = CGAffineTransform(rotationAngle: .pi / 2)
}, completion: nil)
}
I also have a tabbar, where VC0 is one of the root view controllers. Once VC0 has segued to VC1, when you click on to another root view controller and then back, loadingImg is no longer animating. How can I keep loadingImg animating even if I'm using tabbar to switch to different view controllers and back?
You need to set original position of UIView when you switch UIViewController in ViewDidAppear like below
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.loadingImg.transform = .identity
self.view.layoutIfNeeded()
}
I am trying to get my navigation bar to hide when I swipe up and reappear when I swipe down. I print function works but I'm not sure why my navigation bar doesn't hide. Also how do I get the part on top which is an image and a logo to hide on swipe.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if(velocity.y>0) {
UIView.animate(withDuration: 2.5, delay: 0, options: UIViewAnimationOptions(), animations: {
self.navigationController?.setNavigationBarHidden(true, animated: true)
print("Hide")
}, completion: nil)
} else {
UIView.animate(withDuration: 2.5, delay: 0, options: UIViewAnimationOptions(), animations: {
self.navigationController?.setNavigationBarHidden(false, animated: true)
print("Unhide")
}, completion: nil)
}
}
Your can try to hide nav bar in this way
navigationController?.hidesBarsOnSwipe = true
This will automatically hide the bar when you scroll up, and show the bar when you scroll down. It will also handle the resize and animation.
One problem with your code is that scrollViewWillEndDragging is not triggered until you finished dragging, and may be triggered multiple times in one drag action