Content behind custom UINavigationBar? - ios

I created a UINavigationController and a UIViewController. With this setup the view looks like this:
This is what I want. The content "Test Text" does not appear behind the status bar.
Now I created my own UINavigationBar in the UIViewControllers:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false)
let newNavBar:UINavigationBar = UINavigationBar(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 64))
newNavBar.tintColor = UIColor.whiteColor()
newNavBar.translucent = true
self.view.addSubview(newNavBar)
}
The result is the following:
The content is behind the new navigation bar.
How can I prevent the content from being behind the new navigation bar?

When you add Navigation Bar in view controller then NavigationBar will take 64pixel ( 20 pixel status bar and 44 pixel navigation bar ) so you need to start your layout after 64pixel from top.

If your content is a UIScrollView, use the contentInsets property to adjust where your content starts, this makes the scrollview be able to scroll the specified amount of pixels "too far", and thus show your content immediately below your custom UINavigationBar.
If your content is not a UIScrollview, then just offset the content with a constraint (you could link it to an IBOutlet, so you can change it if you dynamically change from the old to the new UINavigationBar).

Related

CollectionView items are hidden behind top bar

I have a messaging application, the problem is that the first messages are not visible, when I drag the collection view to see the top messages I can see them but when I release the finger, the collection view jumps back, hiding the first 5 messages that are at the top of the screen
As we can see from the image there is a message (actually are 5 messages at the top), however I have to drag the collection view to peek those messages. I thought that the size of the collection view is actually larger that the screen, however both the collectionView.frame.height and the UIScreen.main.bounds.height have the same height, is that ok? .
Here's the code that I use to setup the collection view:
/// Function that configures the ChatViewController collection view
private func configureCollectionView() {
collectionView?.backgroundColor = Theme.current.chatGeneralBackground
collectionView?.alwaysBounceVertical = true
collectionView?.keyboardDismissMode = .onDrag
// Register the chat cell and the loading cellx`
collectionView?.register(ChatCell.self, forCellWithReuseIdentifier: chatCellIdentifier)
collectionView?.register(LoadingCollectionViewCell.self, forCellWithReuseIdentifier: loadingCellIdentifier)
// Initialize the original height of the collection view
collectionViewOriginalHeight = collectionView.frame.height
}
What am I doing wrong?
As of iOS 7.0, all views automatically go behind navigation bars, toolbars and tab bars to provide what Apple calls "context".
For example, if you don't want a view controller to go behind any bars, use this in viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.edgesForExtendedLayout = []
}
It seems to be the problem with constraints, if you are using custom navigation bar top constraints should be in reference to it. If using default navigation controller, you might need to give the top constraint to 44 from safe area.
However UIScreen.main.bounds.height consists of complete screen including the top navigation bar and 20 px of status bar. For collectionView.frame.height you need to minus these values.

My ViewController WITH Large Navigation Bar Scrollers up automatically After loading WKWebView

In my app, I am loading about the page in a view controller with a WebKit WebView, and Viewcontroller has a Large Navigation Controller. At time of view DidLoad Large navigation bar is shown fine.
At this point when I start loading my WebView with a local HTML file.
After loading this WebView, without any user interaction, ViewController automatically scrolls up such that navigation bar shrink to actual small-sized form.
Yes this is the default behaviour of navigation bar if you want to set large navigation bar all the time then you have to go with custom navigation bar. Create your own Navigation bar. Thanks
What will help you is the use of viewLayoutMarginsDidChange() .Using this you can check in everyview if the view size has changed and if so you can set your original navigation title size here , So instead of what i have added , parse your Navigation bar frame values below.
var didChange = false
override func viewLayoutMarginsDidChange() {
if didChange {
print("Height : - \
(self.navigationController?.navigationBar.frame.size.height)")
// set NavigationBar Height here
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width:
UIScreen.main.bounds.width, height: 96.0)
didChange.toggle()
}
}
Try getting the scroll events of wkWebView.srollView in scrollViewDidScroll , see if something make it scroll.
Or , disable WKWebView.scrollView.scrollEnabled when loading the WebView and enable it back when load completes
Change the contentInsetAdjustmentBehavior property of the ScrollView of WebView to .never in your viewDidLoad method.
webView.scrollView.contentInsetAdjustmentBehavior = .never
You can try :
webView.scrollView.contentInsetAdjustmentBehaviour = .never

Static/fixed Navigation Bar in iOS

I have a Navigation Controller and a Collection View under it inside my app. And there is a problem: I use large title inside my Navigation bar, so everything inside is not static. When I scroll the collection view cells, the title (I created it manually using UILabel() to move it as I want inside the navigation bar) and buttons move up and the navigation bar takes form of iOS 10 navigation bar, I mean its height. You can see it here:
The normal state of my Navigation Bar with "Prefer large titles" On:
It happens when I scroll my Collection View, everything goes up:
So the question is simple: how to make the force constant height for the navigation bar? I want it to become fixed even while scrolling. Are there any ideas? Is it possible?
And the second question, if the first is impossible: Another solution for my problem is to make the Navigation Bar with "Prefer large titles" Off bigger. I tried this code:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 50 //whatever height you want to add to the existing height
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
but it worked only for large titles. So how can I make the navigation bar bigger?
Yes, you can make it fixed. It will not scroll if the very first view in the view hierarchy is not a CollectionView/TableView (ScrollView).
Using Storyboard/Xib:
Consider the following image where a tableView and button are added in scene. Here the navigation bar will collapse on scroll of tableView because tableView is the very first view in viewController's containerView hierarchy attached to the navigation bar.
Now to make the navigation bar fixed, if we just change the order of tableView and button as below, it will disable the collapsing of navigation bar.
To change the order of the view, you have to click, hold and move up/down.
If you have only CollectionView in this scene then you can add a placeholder view at the top and set its height to zero as below,
Programmatically:
If you are setting up view's programmatically then you just need to add a placeholder view at the top or add tableView/collection after adding other views.
e.g,
self.view.addSubview(UIView(frame: .zero))
self.view.addSubview(tableView) // or collectionView

View doesn't go under status bar and status bar is black

I'm hiding the Navigation Bar on one of the screens, and if is set:
navigationController?.navigationBarHidden = true
The status bar becomes black. Also, the image doesn't fit all the screen (see the screenshot).
If I comment this line, Navigation bar stays on screen, and the status bar is white.
Full code:
override func viewWillAppear(animated: Bool) {
navigationController?.navigationBarHidden = true
navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
navigationController?.navigationBar.translucent = true
navigationController?.navigationBar.backgroundColor = UIColor.clearColor()
navigationController?.view.backgroundColor = UIColor.clearColor()
All constraints of ImageView are set to 0 and it's set to fill the screen:
So, I want to put ImageView under the status bar and make the status bar icons/text white. What I'm doing wrong?
You're not doing anything "wrong". You have set the top of the image view to the bottom of the view controller's top layout guide. Well, that's the bottom of the status bar — exactly where you see the top of the image view.
If you want the image view to underlap the status bar, its top needs to be pinned to the top of the main view, not the top layout guide.
And if you want the status bar to change text color, you need to implement preferredStatusBarStyle to return .LightContent. If this means that the result of preferredStatusBarStyle has changed, you would need to call setNeedsStatusBarAppearanceUpdate to alert the runtime to this fact.
To place the image view under the status bar, and have the image view fill the UIViewControllers view:
Clear all constraints for the image view
Add a constraint to set the image view to have the same width as the parent view
Add a constraint to set the image view to have the same height as the parent view
Pin the image view to the nearest neighbor as shown below. Add the constraints
The final constraints will look like the following:

Autolayout with Navigation Bar - Remove Specific Constraint

I'm building an application for iOS, which is using a navigation controller. I want to put a view in the titleView, and have it fill the whole width of the navigation bar.
I'm calling setupNavBar in viewDidLoad of the view controller that is embedded in the navigation controller. Here is how I do:
func setupNavBar() {
let navBar = navigationController?.navigationBar
// navBar!.translatesAutoresizingMaskIntoConstraints = false
// navBar!.frame.size.height = CGFloat(100)
let searchBar = UIView(frame: navBar!.frame)
searchBar.bounds = CGRectMake(0, 0, navBar!.frame.width, navBar!.frame.height)
searchBar.backgroundColor = UIColor.brownColor()
navigationItem.titleView = searchBar
}
But the view (brown - "searchBar"), doesn't cover the full navigation bar:
So I figured out that the problem was related to Autoresizing and Constraints, because if I call navBar!.translatesAutoresizingMaskIntoConstraints = false, I can freely set the sizes of views frame, so there must be some constraints that change the view's bounds. But I would like to keep as much of the autolayout behaviour as possible.
Is there a way to only change the contraints on the titleView?
I'm doing everything programmatically, I don't use the storyboard or xib's!
EDIT:
But it doesn't seem like there is any constraints on either navigationItem or navBar:
for someObject in navigationItem.titleView!.constraints {
print(someObject)
}
It doesn't print any constraints. neither if I use navBar.constraints!
EDIT 2:
I have a screenshot from "View UI Hierarchy" from the debug navigator:
It seems that the view(brown) alligns with the Navigation Bar Back Indicator View, maybe this is a clue to what causes the problem?
How come the view is resized?
Two different suggestions here:
1. You can try the
navigationItem.titleView.sizeToFit()
Otherwise you could set the background colour of the navbar to brown as it appears you wish the brown bar to cover the entire width of the navbar. If you want to add other views on top of that you then can.
You could also try to make an outlet to the title view and add an NSLayoutConstraint using
navigationItem.titleView.addConstraint(NSLayoutConstraint: NSLayoutConstraint)
I am not entirely sure whether that will work, however.

Resources