Why is my navigation item/bar very dark in colour? - ios

I am building a help screen view controller of my app. It basically contains a UIWebView because I want to use HTML to display the help text. There is also another view controller which is kind of the "main" VC. There is a "Present as Popover" segue connecting the two.
From the IB, I see this:
I have an unwind segue that unwinds to the main VC. It will be triggered if the user taps the "Done" button.
And here is my code:
import UIKit
class HelpViewController: UIViewController {
#IBOutlet var webView: UIWebView!
override func viewDidLoad() {
automaticallyAdjustsScrollViewInsets = false
let htmlString = "You don't need to know about this."
webView.loadHTMLString(htmlString, baseURL: nil)
}
#IBAction func doneClicked(sender: UIBarButtonItem) {
performSegueWithIdentifier("exitToMain", sender: self)
}
}
And the unwind segues are working perfectly but the navigation bar is somehow very dark in colour!
I don't know what's happening here. I checked out this question
iOS 7 SDK - UI Navigation Bar is sometimes darker and sometimes not. But why?
The asker said that's because of a piece of code that he wrote but I swear I didn't use the same code as he did (from my limited obj-c to swift translation knowledge)!
Anyway, here is the relevant storyboard hierarchy thingy:
What causes this problem and how to fix it?

I solved the problem by setting the background colour of the UIWebView to white. And the navigation bar turns white!
I found this by observing how the colour changes when I scroll the web view up and down. I saw that initially it is kinda grey. But when I scrolled down to the white part of the web view, it changes to white. I deduced that the grey colour is actually the web view's background property and the navigation bar is kind of translucent.
And that's why setting the background colour to white fixes this issue.

Stretch the web view through the bottom of the navigation bar and set automaticallyAdjustScrollviewInsets to true. That would adjust the scroll view inset to show the content at the right content.

did you try this
self.navigationController!.navigationBar.translucent = true

Related

How to use scrollEdgeAppearance in iOS 15?

Here's Apple's document of scrollEdgeAppearance for UINavigationBar:
When a navigation controller contains a navigation bar and a scroll
view, part of the scroll view’s content appears underneath the
navigation bar. If the edge of the scrolled content reaches that bar,
UIKit applies the appearance settings in this property.
If the value of this property is nil, UIKit uses the settings found in the
standardAppearance property, modified to use a transparent background.
If no navigation controller manages your navigation bar, UIKit ignores
this property and uses the standard appearance of the navigation bar.
When running on apps that use iOS 14 or earlier, this property applies
to navigation bars with large titles. In iOS 15, this property applies
to all navigation bars.
Here's my demo. I embed ViewController into a UINavigationController, then drag a UITableView and set it as the subview of ViewController's view. I set the following appearance properties to UINavigationBar:
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let redAppearance = UINavigationBarAppearance()
redAppearance.backgroundColor = .red
navigationController?.navigationBar.standardAppearance = redAppearance
let greenAppearance = UINavigationBarAppearance()
greenAppearance.backgroundColor = .green
navigationController?.navigationBar.scrollEdgeAppearance = greenAppearance
}
}
I thought the initial navigation bar should be red, and it should turn green when I scroll the table view. But the truth is it's the other way around.
I did some search and most people just set standardAppearance and scrollEdgeAppearance to the same instance, or set one of them to be nil, so I'm quite confused about these two properties in iOS 15.
You have understood perfectly but backward.
navigationController?.navigationBar.scrollEdgeAppearance = greenAppearance
means the nav bar will be green only when the scrollable view is scrolled all the way down. That is what you see in your first screen shot.
As soon as you scroll up a little bit, the nav bar starts adopting its standard appearance, which is red. That is what you see in your second screen shot.
scrollEdgeAppearance is applied when the edge of the scrollable content reaches the nav bar so what you're seeing is correct. Many people set both scrollEdgeAppearance and standardAppearance to the same since they want the behavior to be no different when the user scrolls but your implementation is certainly a valid use case.

Navigation bar buttons set during viewDidLoad don't appear until after view has appeared in iOS 11

In iOS 10, I could determine the list of navigation bar buttons I want to appear in viewDidLoad, and they would appear in the navigation bar as the view controller transitioned in.
In iOS 11, I can no longer do this. Whatever navigation bar buttons were set in interface builder are displayed as the view controller transitions in, and my custom list of buttons are not displayed until after the view finishes sliding in. Updating the buttons in viewWillAppear does not help.
Is this simply a bug in iOS 11, or is there something else I should be doing? Is there a workaround so I can continue to display buttons while the screen loads?
In the following example, I have set a button "Default Button" in the storyboard, and override it with an "Edit" button in viewDidLoad. The project is available on Github.
iOS 10
iOS 11
It looks like the issue is that navigation bar icons displayed during the transition appear to be fixed when the view controller is passed off to the navigation controller. By the time that viewDidLoad is called, the icons have already been fixed.
In order to fix this, we need to update the navigation bar icons on the view controller's navigationItem before the view controller is pushed onto the navigation controller stack.
One way to do this would be to setup the navigation bar icons in awakeFromNib. This is what #Joe's answer was effectively doing, because apparently viewDidLoad is called from awakeFromNib when isViewLoaded is true during awakeFromNib.
However, doing this in awakeFromNib prevents you from taking into account any properties set on the view controller in prepareForSegue. So another option (and the one that I am using) is to force the entire view to load in prepareForSegue by adding the line _ = controller.view after setting any desired properties.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
...
_ = controller.view
}
}
}
Move your Edit barButton code from viewDidLoad to isViewLoaded method as below.
override var isViewLoaded: Bool {
self.navigationItem.rightBarButtonItem = self.editButtonItem
return true
}
Output:
Note: Above code will fix the transition delay issue. Really, don't have much to explain why this happening. I experienced similar issue in iOS 10 as well NavigationBar delay updating barTintColor iOS10. It could be another bug in iOS11.
PS:
After reading Apple Doc about isViewLoaded and comparing other view loading methods. Its all about loading memory upon view loads.
You don't really need to move you barButton code at all.Just implement the isViewLoaded method and return to true as below:
override var isViewLoaded: Bool { return true}

iOS 11 on NavigationBar pull down - height of bar changes?

What I want to to: I want to drag down the whole view of a viewController to dismiss to the parent viewController using a pan gesture recognizer.
The Problem: When I drag the view down, the navigationBar decreases its height and does not look good. When the view returns to its original position, the navigationBar returns to the default size. I want the navigationBar to stay at its size. I also tried to use the new large titles and some other properties of the navigationController/-bar, but that did not solve it.
Note: Everything worked fine already before iOS 11.
My code:
override func viewDidLoad() {
super.viewDidLoad()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(dragViewDown(_:)))
navigationController!.view.addGestureRecognizer(panGesture)
}
#IBAction func dragViewDown(_ gesture: UIPanGestureRecognizer) {
if let dragView = gesture.view {
let translation = gesture.translation(in: dragView)
dragView.center.y = (dragView.center.y + translation.y)
gesture.setTranslation(CGPoint.zero, in: dragView)
}
}
This test project only has one viewController and does not provide the dismissal, but the problem is the same as in my working project.
I also uploaded the project to GitHub: https://github.com/maddinK7/navitationBar-pull-down-problem
Does anyone have an idea how to solve this? Thanks in advance.
I want the navigationBar to stay at its size
It is staying at its size. If you check the navigation bar's bounds size height before, during, and after the drag, you will see that it remains the same (probably 44) at all times. What's changing is the drawing extension that causes the drawing of the nav bar to extend up behind the status bar. It can't do that when you pull the whole thing away from the top of the screen, because it is not at the top next to the status bar any more. iOS 11 is more strict about the way it performs this drawing extension, probably because it has to do it in a special way on the iPhone X.
So, let's make sure you're doing this correctly:
Make sure that the navigation bar has a top constraint pinned to the safe area layout guide's top, with a constant of zero.
Make sure that the navigation bar has a delegate that returns .topAttached from position(forBar:).
If you are doing both those things and it doesn't help, you'll have to implement this in some other way entirely. Making the view directly draggable like this, without a custom parent view controller, was always dubious.
When UINavigationController attached top, system will add safe area top margin in the navigation background.
(NOTICE: Background margin will not changed when offset value is between 1 and 0)
So you have to handle attached/detached top event by handle gesture offset to change the right offset and content insets.
You can try the solution in my lib example. ;)
My example include UITableViewController in the UINavigationController, so it will relatively complex.
https://github.com/showang/OverlayModalViewController

Navigation controller's toolbar not being hidden after enabling hide on tap?

I have a navigation controller where I have enabled hide on tap.It hides at first when I tap on the screen but when I tap again,the nav bar hides but the toolbar does not hide at all and it is obstructing my view. I have already tried settoolbarhidden and toolbar.hidden properties but it does not work.How do I solve this?
EDIT : I need to hide it only on this screen,I need the toolbar for other screens so thats why I have enabled shows toolbar.
EDIT 2 : Let me frame my question better.
When I enter the view controller :
Both navbar and toolbar hides because I have set it to hidden which is good
When I tap the screen :
Both navbar and toolbar shows because I have set it this way in the previous view controller.(If possible,Can I only show/hide the navigationbar on tap not the toolbar?
And lastly when I tap it again to hide both bars :
The navigation bar hides but the toolbar does not go away? This is my problem.
As Per your question you want to show tool bar on a particular viewController. View Controller viewWillAppear Function Hide ToolBar and viewDidDisappear show your tool bar it will show on other view controllers.
" Please check the navigation controller checkbox its disable or not.After that set this on your view controller before your profile view controller "
override func viewWillAppear(animated: Bool) {
self.navigationController?.toolbarHidden = true;
}
override func viewDidDisappear(animated: Bool) {
self.navigationController?.toolbarHidden = false;
}
I think it will resolve your issue.
I had the same problem.
The hideBarsOnTap only work if you placed smth in it. So if it is empty it will stay.
You could just put a blank imageView or Label there for example.
Or if you want it completely blank, your only option is to put a tabGestureRecognizer on your View!

Xamarin iOS Navigation Bar 100% Transparency

i´m developing an iOS-Application with VisualStudio/Xamarin. I have to set the transparency on the navigationbar to 100%. But let me explain the whole thing:
On the first view the navigationbar have a background image set by this code:
var navigationImage = UIImage.FromFile("gradient.jpg");
UINavigationBar.Appearance.SetBackgroundImage(navigationImage, UIBarMetrics.Default);
The first view got several tablecell items, if clicked, a detail view shows up.
On that detail view the navigationbar should be completely transparent! Only the back button and a title should be leftover.
I tried everything from translucent = yes to this solution which i also found here on stackoverflow.
I also tried to set a color to the first navigationbar and then change it on the next view to another color which works, but if i get back to the firstview the navigationbar color stays the same, even if i override the ViewWillAppear-method from the first view where the BarTintColor is set.
Thanks for your help!
greetings
Well, for what it's worth, I actually followed your solution link and translated it to Xamarin. If I put the following code in ViewDidLoad on my VC, the Navigation Bar is completely transparant ;)
this.NavigationController.NavigationBar.SetBackgroundImage (new UIImage (), UIBarMetrics.Default);
this.NavigationController.View.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.ShadowImage = new UIImage ();

Resources