Why doesn't my navigation bar hide on swipe? - ios

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

Related

Button is not clickable in a child viewcontroller

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

Simultaneous UIViewController Transition Animations

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)
}
}

setNavigationBarHidden not working

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)
}

UIView won't animate after Tabbar selects UIViewController

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()
}

Custom Bottom Bar transition to another view in Swift?

So, I've made a custom bottom bar with UIButton's. Now I am trying to replicate the fade in transition so when you click one of the buttons from the bottom bar will send to another view controller and show that view. I managed to do that but my navigation bar it's not a custom one and whenever I switch the views, the main view goes under the navigation bar.
I am using this code:
//MARK: Main view
func yourFoodGoalAction() -> Bool {
print("transition: YourFoodGoal")
let nextViewController = YourFoodGoal()
let toView = nextViewController.view
UIView.transition(from: view!, to: toView!, duration: 0.3, options: [.transitionCrossDissolve]) { (true) in
print("disolve")
UIView.animate(withDuration: 0.3, animations: {
self.navigationItem.title = "Your Goal"
})
}
return true
}
And to go back to the view (vice versa):
func selectedBarButtonAction() -> Bool {
print("transition: YourFoodGoal")
let nextViewController = YourFoodVC()
let toView = nextViewController.view
UIView.transition(from: view!, to: toView!, duration: 0.3, options: [.transitionCrossDissolve]) { (true) in
UIView.animate(withDuration: 0.3, animations: {
self.navigationItem.title = "Today's Meals"
})
}
return true
}
What should I do so my views will not go under the navigation bar once I change between them? I do not want to use container view as every view will be custom. Everything it's being made programmatically.
I found my answer. I was calling the modal transition wrong. Modals go full screen with the main view. I just embedded the navigation when I am presenting the new view and call the modal from there:
func todaysMealsAction() {
let yourFoodVC = YourFoodVC()
yourFoodVC.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
let navBarOnModal: UINavigationController = UINavigationController(rootViewController: yourFoodVC)
self.present(navBarOnModal, animated: false, completion: nil)
}

Resources