iOS: Adding navigation bar to Application window collides with status bar - ios

I have added navigation bar into application window but navigation bar collides with status bar. (I need to do it with application window).
Code I’ve tried is:
UIWindow * firstWindow = [UIApplication sharedApplication].windows[0];
UINavigationBar * navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, firstWindow.frame.size.width, 64)];
/*
// I tried these also
UINavigationBar * navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, firstWindow.frame.size.width, 84)];
UINavigationBar * navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 20, firstWindow.frame.size.width, 64)];
*/
[firstWindow addSubview:navBar];
Here are results:
I looked around these and tried all answers related to default navigation bar but nothing works:
What is the height of Navigation Bar in iOS 7?
iOS 10 custom navigation bar height
iOS 7 status and navigation bar different height in storyboard than in app
UINavigationBar/Status Bar issue in IOS7
When hiding the statusbar my navigation bar moves up in iOS7
iOS 7 Status Bar Collides With NavigationBar using ViewController

Use additionalSafeAreaInsets for NavigationController,
self.navigationController.additionalSafeAreaInsets = UIEdgeInsetsMake(20, 0, 0, 0);

This is how you would do it in iOS 11 using the safe area insets. You need a view controller under the hood so you can at least get notified when the safe area insets are updated. This code is from the single app template in Xcode 9. You can see the frame update between portrait and landscape mode as the safe areas are updated.
import UIKit
class ViewController: UIViewController {
private var window: UIWindow!
private var navbar: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
self.window = UIApplication.shared.windows[0]
self.navbar = UINavigationBar(frame: CGRect(x: 0, y: self.view.safeAreaInsets.top, width: window.frame.size.width, height: 64))
self.navbar.barTintColor = .red
window.backgroundColor = .gray
window.addSubview(navbar)
self.view.backgroundColor = .clear
}
override func viewSafeAreaInsetsDidChange() {
let navBarHeight: CGFloat = 64
self.navbar.frame = CGRect(x: 0, y: self.view.safeAreaInsets.top, width: self.window.bounds.width, height: navBarHeight)
}
}
Here is an image from the simulator:
If you need to support iOS 10 and below then you need to also use the topLayoutGuide which was deprecated. The length property will give you similar information as the safe layout guides.
I feel compelled to add though that finding a way to use the navigation controller would be much easier and safer to use especially as you start supporting multiple versions of iOS and Apple upgrades UIKit.

Try this
CGFloat height = [UIApplication sharedApplication].statusBarFrame.size.height;
UIWindow * firstWindow = [UIApplication sharedApplication].windows[0];
UINavigationBar * navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, height, firstWindow.frame.size.width, 64)];
[firstWindow addSubview:navBar];

Related

Why iOS 11Custom UINavigationItem titleView and leftBarButtonItem are varying from iOS9?

My Puzzle is "Why iOS 11Custom UINavigationItem titleView and leftBarButtonItem are varying from iOS9?".
When I customize titleView and leftBarButtonItem in navigationItem of my HomeViewController, I found something different here.
The following code successfully places the custom leftBarButtonItem and custom titleView in the navigation bar.
// customize leftBarButtonItem
_customLeftItemView.frame = CGRectMake(0, 0, 60, 40);
UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(clickLeftItemAction:)];
[_customLeftItemView addGestureRecognizer:tapGes];
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:_customLeftItemView];
leftItem.width = 60.0f;
self.navigationItem.leftBarButtonItem = leftItem;
// customize titleView
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 250, 40)];
searchBar.placeholder = #"Please search address";
searchBar.delegate = self;
self.navigationItem.titleView = searchBar;
The _customLeftItemView is like the figure below.customLeftItemView In Storyboard
Above the code executed,the appearance difference between iOS11 and iOS9, like the figures below.iPodSimulator iPhone8 iOS11
When I checked the difference through Debug View Hierarchy tool, I found searchBar occupies the entire area of the UINavigationBarContentView and UISearchBarTextField on the right side of the UIButtonBarStackView when App ran in iPhone 8. however when App ran in iPod(iOS 9), searchBar didn't occupy the entire area of the UINavigationBarContentView, it is on the right side of the UIButtonBarStackView. the code _customLeftItemView.frame = CGRectMake(0, 0, 60, 40); is effective in iOS9, so the leftBarButtonItem width is fixed, if run in iOS11, it loses effectiveness. the difference like the figures below.iPod Debug View Hierarchy iPhone8 Debug View Hirarchy
Could you help me with this?
Thanks for your help.

Swift - UISearchBar in UIToolbar

How can I create A UISearchBar inside of a Toolbar in Swift? If I use the Interface Builder I get the following error:
error: Illegal Configuration: UISearchBar embedded in UIBarButtonItems (Only available in iPad documents)
Is there a Swift solution for this problem? The Toolbar will only be available on iPad.
UIToolBar is just a custom UIView, so you have three options (that I can see) for your implementation:
First, if you want to stick the search bar in the toolbar here's the code:
var searchBar = UISearchBar(frame: CGRectMake(0, 0, 100, 50))
var myView = UIView(frame: searchBar.frame)
myView.addSubview(searchBar)
var barButtonItem = [UIBarButtonItem(customView: myView)]
toolBar.setItems(barButtonItem, animated: false)
Second, if you want the search bar in the nav bar on your screen you can do the following:
let searchBar = UISearchBar(frame: CGRectMake(0, 0, 300, 50))
navigationController?.navigationBar.addSubview(searchBar)
Third, if you need the toolbar to be elsewhere, you can create your own custom UIView that looks like a toolbar (spans the width of the screen) and add the search bar to that. You can even make this new toolbar of yours a custom class so it's reusable throughout your program.
Cheers!

How to increase the height of navigation bar in Xcode?

I'm working on a app, in which I need to keep a navigation bar.
when I write any title on the bar, the time and the title kinda get very close to each other. I wanted to increase the height of the bar, so it can get some breathing room.
select your ViewController --> select your Navigation Item --> Prompt --> Add space it increase the height of **Navigation bar**
Check Image here :
Programatically
Add this in viewWillAppear or viewDidAppear method
Objective-C
[self.navigationController.navigationBar setFrame:CGRectMake(0, 0, self.view.frame.size.width,80.0)];
Swift
self.navigationController.navigationBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 80.0)
Swift-3
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 80.0)
iOS 11
objective C
for (UIView *subview in self.navigationController.navigationBar.subviews) {
if ([NSStringFromClass([subview class]) containsString:#"BarBackground"]) {
CGRect subViewFrame = subview.frame;
// subViewFrame.origin.y = -20;
subViewFrame.size.height = 100;
[subview setFrame: subViewFrame];
}
}
swift
for subview in (self.navigationController?.navigationBar.subviews)! {
if NSStringFromClass(subview.classForCoder).contains("BarBackground") {
var subViewFrame: CGRect = subview.frame
// subViewFrame.origin.y = -20;
subViewFrame.size.height = 100
subview.frame = subViewFrame
}
}
simply add this line to your viewController
navigationController?.additionalSafeAreaInsets.top = 30
// where 30 is the extra space, add as per your need.
Apple proposes not to resize navigationBar itself, but remove shadow from bar and add custom view under your navigationBar. This can work for most cases. Check Apple's samples.
Add the following extension to your project:
import UIKit
extension UINavigationBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.size.width, height: 80.0)
}
}
Please refer the apple recommended approach for extended navigation bar here,
https://developer.apple.com/library/content/samplecode/NavBar/Introduction/Intro.html
THIS SOLUTION NO LONGER WORKS IN Xcode 8.x.x and later!
you can also increase height without creating the custom navigation follow the following steps
Step 1 Selecte Navigation bar in Storyboard or XIB
Step 2 Copy ObjectID from Identity Inspector
Step 3 Open Storyboard/XIB as Source Code
Step 4 Find ObjectID in Source Code past ObjectID in search
Step 5 Edit height! thats all
I hope this will help you
Add this in viewWillAppear method
CGFloat height = 80;
[self.navigationController.navigationBar setFrame:CGRectMake(0, 0,
self.view.frame.size.width,height)];
if it increase first and shrinks to original height then add this code in viewDidAppear method
We need to change the height of the navigation bar for each time the view show.So put the code on viewWillAppear
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 80)
}
we can set the width as the width of the view and change the height as we wish.
You can't change the height of the default NavigationBar if I'm not wrong.
Although, you can create a custom NavigationBar and add a custom height to it.
navigationController?.additionalSafeAreaInsets.top = 25
Add this to viewDidLoad. it will definitely work. Successfully worked in Xcode 12-version
[self.navigationController.navigationBar setPrefersLargeTitles:YES];
is going to Increase the Navigation bar height Programmatically

iOS hidesBarsOnSwipe status bar background color

When I swipe and hide the navigation bar with the hidesBarsOnSwipe property the status bar has a clear background. How can I set the background of the status bar to the same color as the navigation bar? Here are a few pictures showing my problem, this is all contained in a UITableViewController.
Separate
Separate picture, looks like one big one.
I've come across the same issue, and was able to solve it. I'm fairly new to iOS dev, and I don't imagine this solution to be foolproof. I couldn't find any good answers elsewhere, so here's how I overcame it:
I converted from a UITableViewController over to UIViewController with a nested UITableView. Note, double check that the delegate to the child tableview is set to the UIViewController.
I Added a view with a height of 20px and a background colour that you want to set as the "background" to the status bar. Set the constraints on that view as follows:
On your table view, set the constrains to be basically full screen. One important note here, the top constraint is to "Top Layout Guide.Top" and not to "Top Layout Guide.Bottom". By default I believe this constraint ties to the bottom. Double clicking on the constraint allows you to adjust it to the top. Without this, any table header cells weren't positioned properly for me
Hope that helps.
Adding to George Huber's answer. I solved this issue programmatically by adding a 20pt height UIView as a subview of the navigationController's view property -- in viewDidLoad method.
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *statusBarBG = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 20)];
statusBarBG.backgroundColor = [UIColor navBar];
[self.navigationController.view addSubview:statusBarBG];
// REST OF CODE
}
Per skg's answer, I add a relative height for status bar according to iOS version.
self.navigationController.hidesBarsOnSwipe = true;
// add a UIView as subView to navigationController
CGFloat statusBarHeight;
if (#available(iOS 13, *)) {
NSArray *windows = UIApplication.sharedApplication.windows;
UIWindow *keyWindow = nil;
for (UIWindow *window in windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
statusBarHeight = keyWindow.windowScene.statusBarManager.statusBarFrame.size.height;
NSLog(#"statusBarHeight: %f", statusBarHeight);
} else {
statusBarHeight = UIApplication.sharedApplication.statusBarFrame.size.height;
}
UIView *statusBarBG = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), statusBarHeight)];
statusBarBG.backgroundColor = [UIColor systemBackgroundColor];
[self.navigationController.view addSubview:statusBarBG];

iOS: dimensions of search bar in navigation controller

I have a UISearchBar in my navigation controller bar title view. I followed the first answer here How to add search bar in navigation bar for iphone?. This works for me but the dimensions of the search bar are hardcoded. How can I set the dimensions so that it looks nice on iPad and iPhone in both portrait and landscape mode?
This is the code in my search bar controller.
self.view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 310.0, 44)];
self.view.autoresizingMask = 0;
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(-5.0, 0.0, 320.0, 44.0)];
_searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_searchBar.delegate = self;
[self.view addSubview:_searchBar];
Then in my main viewController I have
self.navigationItem.titleView = _searchController.view;
There are many ways to do this, and here are some articles that may be helpful:
Get the device's orientation, then use different sets of values accordingly
Figure out which device the app is running on
Get the dimension of the screen

Resources