How to implement hiding the UITabBar to display an UIToolbar on iOS 11 and iPhone X - ios

I'm trying to do an UI similar to the Photos app, where when you enter in a selection mode that hides the tab bar to display a toolbar.
I have my view controller in a UINavigationController and the navigation controller in a UITabBarController.
I had other strategies before but I'm struggling to get this working on the iPhone X and its bottom safe margins.

If I'm making the correct assumptions based on your description of the Photos App, I think you may be confused as to what the app is doing behind the scenes when going from Photos App TabBar to Photos App Toolbar.
These are two different ViewControllers, the second only shows the toolbar and sets hidesBottomBarWhenPushed = true in the init. You can use the NavigationController's supplied toolbar by setting the setToolbarItems(toolbarItems: [UIBarButtonItem]?, animated: Bool) in your second ViewController. This properly sizes the toolbar in the view to account for the bottom control on the iPhoneX.
If you must manage toolbar and TabBar visibility in the same ViewController, based on my testing, you'll need to add/manage the toolbar manually within a UIView container to get the proper size on all devices. So the view hierarchy would be ViewController.view -> toolbarContainer View -> Toolbar.

for iPhone X, the tab bar height is different than iPhone 8, you need to track
static CGFloat tabBarMaxHeight = 0;
- (void)setToolbarHidden:(BOOL)hidden {
[self.navigationController setToolbarHidden:hidden animated:NO];
CGRect frame = self.tabBarController.tabBar.frame;
tabBarMaxHeight = MAX(tabBarMaxHeight, CGRectGetHeight(frame));
frame.size.height = hidden ? tabBarMaxHeight : 0;
self.tabBarController.tabBar.frame = frame;
self.tabBarController.tabBar.hidden = !hidden;
//! reset tab bar item title to prevent text style compacted
for (UITabBarItem *obj in self.tabBarController.tabBar.items) {
NSString *title = obj.title;
obj.title = #"";
obj.title = title;
}
}

Related

Navigation bar not appear properly in IOS 13

In here, I have hide the default navigation bar and created a custom navigation bar. When run on iOS 13 device using Xcode 11 two navigation bars showing.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
Navigation bar not aligned to the top of the screen properly after updating to iOS 13
Any help will be appreciated.
Try the safeAreaLayoutGuide
Apple: The layout guide representing the portion of your view that is unobscured by bars and other content.
In your viewcontroller, if you want to use the full screen and override the navigationbar entirely with your own subclass, then make sure you do this in the initilizer and the viewwill appear methods
[self.navigationController setNavigationBarHidden:true animated:true];
[self setExtendedLayoutIncludesOpaqueBars:true];
from there, you have to access the values of the top layoutguide which will be 44 points and 20 points depending on the size of the iphone you accesss those this way in loadview or viewdidload or a custom subclass
UIWindow *window = UIApplication.sharedApplication.keyWindow;
CGFloat topPadding = window.safeAreaInsets.top;
then the frame of your custom navigation bar is then calculated like so:
CGRect tempRect = CGRectMake(0, 0, self.view.frame.size.width, topPadding + 44);
44 is there because it's constant across all iphones and ipads for now (this could change in the future and nullify this solution, but this is the standard for now)
that will return correct dimensions for all iphone sizes.
THIS => [self setExtendedLayoutIncludesOpaqueBars:true];
IS ABSOLUTELY necessary to make this work as i explained. this isn't a good idea to travel down this path because very rarely do you ever need to override and replace the navigation bar with some custom UIView, but if you need to do it, this is how you do it. Just know that this will break if you're not updating frame sizes during on call status and other edge case conditions.

Unable to click "under" a hidden TabBar

I hide my tab bar like so:
self.tabBarController.tabBar.hidden = YES;
And because now there is a black bar where it once stood I stretch the view which is a UIWebView on top(or is it under?) that empty space. The UIWebView is in a UIViewController. I do that with a constraint which by default is like so:
The code for the constraint:
if(self.tabBarController.tabBar.hidden){
self.webviewBottomConstrain.constant = -self.tabBarController.tabBar.frame.size.height;
}else{
self.webviewBottomConstrain.constant = 0;
}
However if I tap the device on the place where the TabBar was it will not execute. It is as if there is something invisible there with the size of the tab bar. I have also tried hiding it the way this thread sugests. Still the same result.
Update: It seems that when you tap on the invisible tab bar the tap is recognized by the tab bar and not by the view that is visible under the tab bar
self.extendedLayoutIncludesOpaqueBars = YES;
this will solve you problem
You hide your tabBar by setting its hidden property to NO? Try setting it to YES. Unless I am misunderstanding what you are trying to do, it seems like your tab bar is not hidden with that code.
Another thing I would check is to see if User Interaction Enabled is checked for the web view. If it is not, that can seem like there is something invisible blocking you from interacting with your view.
Well I am using quite ugly hack to fix this. I am hiding the tab bar in another way now:
if (shouldShow) {
self.hidesBottomBarWhenPushed = NO;
UIViewController *someView = [[UIViewController alloc] init];
[self.navigationController pushViewController:someView animated:NO];
[self.navigationController popToViewController:self animated:NO];
} else if (shouldHide) {
self.hidesBottomBarWhenPushed = YES;
self.tabBarController.hidesBottomBarWhenPushed = YES;
self.navigationController.hidesBottomBarWhenPushed = YES;
UIViewController *someView = [[UIViewController alloc] init];
[self.navigationController pushViewController:someView animated:NO];
[self.navigationController popToViewController:self animated:NO];
}
I do need that random view because I cannot push the view on itself.
I had the same issue when hiding the tab bar by moving it offscreen to the bottom. My custom UITabBarViewController was intercepting the touch events in the area vacated by the tab bar, so instead of changing the frame of the tab bar to move the tab bar offscreen, I extended the height of my tab bar view controller so that the tab bar still moved offscreen, but the child view above the tab bar now filled that space. This allowed the touches to be received by the child view.
As you may see with view hierarchy instrument, UITabBar is not directly blocking your tap, but your current view controller's view height is not full screen:
So, the tap doesn't response because your finger's y position is higher than view's maxY.
Code like this (inside your UITabBarController) will expand your view's height, according to tabbar visibility, and all tap events will work correctly.
func updateTabBarAppearanceWithDegree(_ degree: CGFloat) {
let screenHeight = UIScreen.main.bounds.size.height
let tabBarHeight = self.tabBar.frame.size.height
self.tabBar.frame.origin.y = screenHeight - tabBarHeight * degree
self.tabBar.alpha = degree
let currentNavigation = self.selectedViewController as? UINavigationController
if let currentTopView = currentNavigation?.viewControllers.last?.view {
currentTopView.frame.size.height = self.tabBar.frame.origin.y
}
}

Strange UISearchDisplayController view offset behavior in iOS 7 when embedded in navigation bar

I am building an iOS 7-only app. I am trying to set a UISearchDisplayController into the navigation bar.
I have it set up like this: In the storyboard, I added a "Search Bar and Search Display Controller" to my view controller's view, and set it at (0,0) relative to the top layout guide. I set constraints to pin to left, top and right. (I played with the constraints, i removed them completely, it doesn't matter) On top of that I have my Table view. When I added the search bar to the view in the storyboard, it automatically setup outlets for searchDisplayController and searchBar delegate. In code I have self.searchDisplayController.displaysSearchBarInNavigationBar = YES; I have two problems:
1) Without any buttons showing for the search bar (Interface builder -> select search bar -> Options: none selected) the search bar is in the middle of the screen:
If I click on the navigation bar, it starts editing the search bar:
notice also that the dark overlay appears to be offset from the navigation bar. It seems to me that the space is the same height as the navigation bar. Like it has been shifted down by that much. Also, when it displays the search results, the top of the content view is shifted down by the same amount (more pictures follow), which brings me to the second problem.
2) I messed around with it for a while and decided to check the option to have it show the cancel button. Now I have the search bar embedded in the nav bar correctly, but the overlay is still shifted down:
Again, when the search results table view appears, it is shifted down by the same amount (notice the scroll bar on the right side):
Even more bizarrely, I set a border on the search display controller's tableview layer, and it appears correct:
I have never used the UISearchDisplayController before and I unfamiliar with how to set it up, but functionally it works fine. I have read some other similar posts but the only advice is to hack it up by adjusting frames and setting manual offsets. I'd prefer to know what is causing this, is it a bug? Something I'm doing wrong? If it's a bug I can wait for a fix. It seems like such a basic thing that a thousand people must have done without any problem so I feel like I'm not setting it up correctly somehow. Thanks for you input.
I remember running into the same exact problem that you are observing.There could be a couple of solutions you can try.
If you are using storyboards
You should click on the view controller or TableView Controller which you have set up for your tableview and go to its attribute inspector and look under ViewController section and set the Extend Edges section to be under Top Bars.
If you are not using storyboards you can manually set the settings using the viewcontrollers edgesForExtendedLayout property and that should do the trick. I was using storyboards.
In my case, using storyboards, I had to check both Under Top Bars and Under Opaque Bars and leave Under Bottom Bars unchecked.
In my case, I actually had to uncheck all the Extended Edges boxes (essentially the same as programmatically setting Extended Edges to UIRectEdgeNone I believe) in my Storyboard in order to stop my search bar from offsetting itself. Thank you guys!
definesPresentationContext = true
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = true
searchController.searchBar.searchBarStyle = UISearchBarStyle.Prominent
self.tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
or see UISearchBar presented by UISearchController in table header view animates too far when active
My problem was just Adjust scroll view inserts. After change to false I didn't have problem
I had a same problem. And I solve this issue with adding view object under the tableview.
Add new ViewController on the Storyboard
Drag TableView to the new VC
Drag Table Cell to the TableView
Make a Connection for TableView DataSource, TableView Delegate to the new VC
I had very similar behavior happening. For me, the solution was to uncheck Extend Edges Under Top Bar in the storyboard settings for the parent view controller (I've turned off transparent navbars, not sure if that effects anything). If you're not using storyboard, you have to set [UIViewController edgesForExtendedLayout].
From the Apple docs:
This property is only applied to view controllers that are embedded in containers, such as UINavigationController or UITabBarController. View controllers set as the root view controller do not react to this property. Default value is UIRectEdgeAll.
Unfortunately none of the above solutions worked for me, I'm using a UITableViewController.
This link helped:
http://petersteinberger.com/blog/2013/fixing-uisearchdisplaycontroller-on-ios-7/
I put the code below for convenience:
static UIView *PSPDFViewWithSuffix(UIView *view, NSString *classNameSuffix) {
if (!view || classNameSuffix.length == 0) return nil;
UIView *theView = nil;
for (__unsafe_unretained UIView *subview in view.subviews) {
if ([NSStringFromClass(subview.class) hasSuffix:classNameSuffix]) {
return subview;
}else {
if ((theView = PSPDFViewWithSuffix(subview, classNameSuffix))) break;
}
}
return theView;
}
- (void)correctSearchDisplayFrames {
// Update search bar frame.
CGRect superviewFrame = self.searchDisplayController.searchBar.superview.frame;
superviewFrame.origin.y = 0.f;
self.searchDisplayController.searchBar.superview.frame = superviewFrame;
// Strech dimming view.
UIView *dimmingView = PSPDFViewWithSuffix(self.view, #"DimmingView");
if (dimmingView) {
CGRect dimmingFrame = dimmingView.superview.frame;
dimmingFrame.origin.y = self.searchDisplayController.searchBar.frame.size.height;
dimmingFrame.size.height = self.view.frame.size.height - dimmingFrame.origin.y;
dimmingView.superview.frame = dimmingFrame;
}
}
- (void)setAllViewsExceptSearchHidden:(BOOL)hidden animated:(BOOL)animated {
[UIView animateWithDuration:animated ? 0.25f : 0.f animations:^{
for (UIView *view in self.tableView.subviews) {
if (view != self.searchDisplayController.searchResultsTableView &&
view != self.searchDisplayController.searchBar) {
view.alpha = hidden ? 0.f : 1.f;
}
}
}];
}
// This fixes UISearchBarController on iOS 7. rdar://14800556
- (void)correctFramesForSearchDisplayControllerBeginSearch:(BOOL)beginSearch {
if (PSPDFIsUIKitFlatMode()) {
[self.navigationController setNavigationBarHidden:beginSearch animated:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[self correctSearchDisplayFrames];
});
[self setAllViewsExceptSearchHidden:beginSearch animated:YES];
[UIView animateWithDuration:0.25f animations:^{
self.searchDisplayController.searchResultsTableView.alpha = beginSearch ? 1.f : 0.f;
}];
}
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
[self correctFramesForSearchDisplayControllerBeginSearch:YES];
}
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
[self correctSearchDisplayFrames];
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
[self correctFramesForSearchDisplayControllerBeginSearch:NO];
}
- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
// HACK: iOS 7 requires a cruel workaround to show the search table view.
if (PSPDFIsUIKitFlatMode()) {
controller.searchResultsTableView.contentInset = UIEdgeInsetsMake(self.searchDisplayController.searchBar.frame.size.height, 0.f, 0.f, 0.f);
}
}
Go to storyboard.
Click on the view controller.
Go to attribute inspector under the ViewController section.
Set the Extend Edges section to be Under Top Bars and Under Opaque Bars.
Make sure to un-check Under Bottom Bars.

iOS 7 Status Bar Collides With NavigationBar

I have a view controller in my app that has a navigation bar dragged on it in the storyboard. It was working fine in the iOS 6 but in iOS 7 it look like this:
The status bar and the navigation bar should no collide with each other. I have seen a lot of such questions on the stack overflow but they didn't of much help to me.
Some questions say that i should use this "self.edgesForExtendedLayout = UIRectEdgeNone;" but it didn't work. Some say i should remove the navigation bar and embed it inside the navigation controller that i cannot do due to the way my program is implemented. Some solutions suggests to use the view bounds and all but it didn't work for me as well.
What is the one thing that can help me resolve this issue. Thanks in advance!
UPDATE: I have embedded the view controller inside a uinavigation controller. Removed the navigation bar that was earlier manually added in it. Now it looks ok in the storyboard but when i run it, it shows the following:
It is showing text from another view controller that is currently behind it that is its parent view controller. Means its transparent now. Can anyone point out what i am doing wrong?
The latest version of the iOS has brought many visual changes and from a developer's point of view, the navigation and status bar are two noticeable changes.
The status bar is now transparent and navigation bar behind it shows through. The navigation bar image can even be extended behind the status bar.
First of all, if you are a beginner and have just started iOS development and are confused the way status bar and navigation bar is working, you can simply go through a blog post HERE that i found very useful. It has all the information related to navigation and status bar in iOS 7.
Now coming to the answer of your question. First of all i can see two different problems. One is that your status bar and navigation bar are both kind of colliding with each other as shown by you in the question with an image.
PROBLEM: Well the problem is that your have earlier dragged a navigation bar in your view controller which was working in iOS 6 correctly but with the arrival of iOS 7 SDK, this approach is resulting in status bar and navigation bar overlapping with each other.
SOLUTION to First Problem: You can either use UIBarPositionTopAttached or you can use view bounds and frames, i can also suggest and link you to Apple's documentation and bla bla bla but that would take some time for you to solve the issue.
The best and the most easiest way to solve this issue is to just embed your view controller inside a navigation controller and thats it. You can do it by just selecting the view controller and going to Editor > Embed In > Navigation Controller. (If there is any content on your old navigation bar, you can first drag it down, embed the view controller in navigation controller and then move the bar buttons on the new navigation bar and then delete the old navigation bar)
SOLUTION to Second Problem: This solution is for your specific question that you have mentioned in the update and is not for the general public reading this. As you can see that navigation and status bar is not visible and a transparent area is showing the parent view controller. I am not really use why you are facing this issue but most probably because of some third party library like ECSlidingView or any other is involved. You can select this view controller in your storyboard and set the background color of the view to be the same as your navigation bar. This will stop showing the parent view controller behind and your navigation bar and status bar will start showing. Now you can cover the rest of your view controller with text view or what ever your are using in it.
Hope this helps!
The navigation bar is too close to the status bar because starting in iOS 7, the status bar is more of an overlay over the whole view controller's view. Since your navigation bar is at (0, 0), the status bar will show on top of the navigation bar. To solve this, simply move the navigation bar down (or, as others have said), create a constraint between the navigation bar and the topLayoutGuide.
When you do that, you will see that there is now a 20 point gap between the navigation bar and the top of the screen. That's because you just moved the navigation bar down 20 points. "But UINavigationController can do it right!" Absolutely, and it does so by implementing UIBarPositioningDelegate on your view controller. This is a one-method protocol that should be implemented like this:
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar {
return UIBarPositionTopAttached;
}
After adding your view controller as the delegate for the navigation bar, you'll notice the navigation bar is still shifted down 20 points, but its background will extend up underneath the status bar, just like in UINavigationController.
Another thing you're seeing is that the navigation bar is translucent, meaning anything underneath the navigation bar will be visible to some extent. The translucent property on UINavigationBar is set to YES by default on iOS 7. Before iOS 7, the default was NO.
you can simply do this:
1) add a constrain between the Navigation Bar and Top Layout Guide (select navigationBar, hold ctrl key and go to Bottom Layout Guide, unhold ctrl key)
2) select vertical spacing:
3) set constant to 0:
Result:
UPDATE
In your AppDelegate file you can add this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
// Prevent Navigationbar to cover the view
UINavigationBar.appearance().translucent = false
}
I suggest you in your viewDidLoad method you try:
self.navigationController.navigationBar.translucent = NO;
(by default it is yes now)
https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationBar_Class/Reference/UINavigationBar.html#//apple_ref/occ/instp/UINavigationBar/translucent
This works for me i hope you also have same luck :).
Add below code in your view.
-(void) viewDidLayoutSubviews
{
CGRect tmpFram = self.navigationController.navigationBar.frame;
tmpFram.origin.y += 20;
self.navigationController.navigationBar.frame = tmpFram;
}
It basically change location of navigation bar.
This is new feature with IOS7. Instead of staring at 20 px navigation bar in IOS7 staring at 0 px. As a solution shift the whole view downwards to 20 px or you can use image for navigation bar with height 64px.
In case it still helps someone, this is what worked for me for moving the Navigation Bar little bit down in ios 7 and above:
-(void)viewWillLayoutSubviews
{
float iosVersion = 7.0;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= iosVersion) {
// iOS 7+
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += 10;
self.view.frame = viewFrame;
}
}
On a device with ios 6.1 and below the Navigation Bar will be unchanged, as it was before.
And this is what I used to make the contents of the Status Bar lighter:
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
If your UIViewController is NOT in a UINavigationController and you're using UIStoryBoard, you can set the "iOS 6/7 Deltas" to 20 for the delta Y, for every subview that needs to be offset from the UIStatusBar.
Using Swift:
As #Scott Berrevoets said in his answer you need to implement the method positionForBar in the protocol UIBarPositioningDelegate, but as the UINavigationBarDelegate protocol implements this protocol :
public protocol UINavigationBarDelegate : UIBarPositioningDelegate {
...
}
You only need to set the delegate of the UINavigationBar you set using Storyboard and implement the method and it's done, like in this way:
class ViewController: UIViewController, UINavigationBarDelegate {
#IBOutlet weak var navigationBar: UINavigationBar!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func positionForBar(bar: UIBarPositioning) -> UIBarPosition {
return UIBarPosition.TopAttached
}
}
NOTE:
It's worth to mention if you set the position of the y-axis of the navigation bar, let's say to 40 from the top, then it will extend underneath to the top from this position, to simulate the behaviour of the UINavigationController you need to set to 20 from the top.
I hope it will help you.
First, set UIViewControllerBasedStatusBarAppearance to NO in Info.plist.
Then, in AppDelegate's application:didFinishLaunchingWithOptions: method add:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
[application setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.clipsToBounds = YES;
self.window.frame = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height-20);
self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
}
return YES;
In iOS 7 app occupies 100 % of screen size.This not a problem .
http://www.doubleencore.com/2013/09/developers-guide-to-the-ios-7-status-bar/
in earlier iOS window start after statusbar and in iOS 7 window starts from 0px in earlier version view height is 460 (iPhone 4s and earlier) and 548 (iPhone 5) but in iOS 7 view height is 480 (iPhone 4s and earlier) and 568 (iPhone 5 and later) so you have to start view arrangement after 2o px or you have to start view from 20px.
you can write below code in rootviewcontroller or in all viewcontroller for set view from 20px
#define IOS7_HEIGHT 64
- (void)viewDidLayoutSubviews {
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:#"7.0" options:NSNumericSearch] != NSOrderedAscending)
{
CGRect frame=[self.view frame];
if (frame.origin.y!=IOS7_HEIGHT) {
frame.origin.y = IOS7_HEIGHT;
frame.size.height -= IOS7_HEIGHT;
[self.view setFrame:frame];
[self.view layoutSubviews];
}
}
}
here height is 64 because 20 for statusbar and 44 for navigationbar.
try below code it will help you. and your problem will be solved.
For the ones who are having problems implementing #Masterfego 's solution (which is also the official, but I have had problems with Xcode 6.3 and automatic constraints), this is what I did:
I have a UIViewController with an added Navigation Bar. I selected the NAvigation bar and added a height constraint of 64px. We later see a warning that the navbar will be higher (but this is what we do). Finally, you can see that the Status bar looks nice and has the same color as the navbar. :)
PS: I can't post images yet.
You can probably create constraints that are attached to the top layout guide to specify the navigation bar's position relative to the status bar. See the iOS 7 UI Transition Guide: Appearance and Behavior section for more information about using the layout guides.
it's the best answer.
But I wanted know how to use a Storyboard and dragged UINavigationBar on it.
When I implemented the delegate method, and set the return result to UIBarPositionTopAttached, it did not work.
- (void)viewDidLoad{
self.navigationbar.delegate = self;
}
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar{
NSLog(#"Got it");
//
// CGRect frame = self.navigaitonBar.frame;
//
// frame = CGRectMake(0, 20, CGRectGetWidth(frame), CGRectGetHeight(frame));
// self.navigaitonBar.frame = frame;
//
// NSLog(#"frame %f",frame.origin.y);
return UIBarPositionTopAttached;
}
If you use Xcode 6 and Swift, you can make it:
Open to info.plist file of your app.
Add a ViewControllerBasedStatusBarAppearance Boolean key if it is not existing and assign value “NO”.
Add “Status bar style” key if it is not existing and select “Opaque black style” value to it.
I was facing issue when full screen ModalViewController was opening from my MainViewController, NavigationBar position was getting changed when user was coming back to MainViewController from ModalViewController.
Issue which I noticed is status bar height was not getting included when user came back to MainViewController. Please debug and check origin of your NavigationBar before and after coming back to your ViewController.
// This method will adjust navigation bar and view content.
private func adjustNavigationControllerIfNeeded() {
var frame = self.view.frame
let navigationBarHeight = self.navigationController!.navigationBar.frame.size.height
if(frame.origin.y == navigationBarHeight && !UIApplication.shared.isStatusBarHidden) {
// If status bar height is not included but it is showing then we have to adjust
our Navigation controller properly
print("Adjusting navigation controller")
let statusBarHeight = UIApplication.shared.statusBarFrame.height
frame.origin.y += statusBarHeight // Start view below navigation bar
frame.size.height -= statusBarHeight
self.view.frame = frame
self.navigationController!.navigationBar.frame.origin.y = statusBarHeight // Move navigation bar
}
}
And call it from viewWillAppear method -
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.adjustNavigationControllerIfNeeded()
}

iOS 7 status bar transparent

In storyboard, in a view controller I tried add a navigation bar under the status bar, running it, it is transparent and shows a label that's supposed to be blurred, like by navigation bar.
But when placing the same view controller embedded in a navigation view controller, the underneath background image could be blurred, which is my intention.
What are these two way different results? What need to do for the firs method to make status bar blur?
Thanks!
In iOS 7 the status bar is transparent by default. The blurring you're seeing when there's also a navigation bar is actually created by the navigation bar. So to create the effect you're looking for without a navigation bar, you need to position a view that produces a blurring effect beneath the status bar.
For reference, add your view with a frame provided by:
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
I know this is old, just for reference, I solved this by setting self.navigationController.navigationBar.clipToBounds = NO
I haven't tested this completely, but go to your plist file and check the following settings:
"View controller-based status bar appearance": If this is set to "Yes", then it should display a status bar that is unique to each View Controller, which might be what you need.
"Status bar style": You may set this to three different styles: Opaque black, Gray, and Transparent black.
Let me know if this worked for you.
UINavigationController will alter the height of its UINavigationBar to either 44 points or 64 points, depending on a rather strange and undocumented set of constraints. If the UINavigationController detects that the top of its view’s frame is visually contiguous with its UIWindow’s top, then it draws its navigation bar with a height of 64 points. If its view’s top is not contiguous with the UIWindow’s top (even if off by only one point), then it draws its navigation bar in the “traditional” way with a height of 44 points. This logic is performed by UINavigationController even if it is several children down inside the view controller hierarchy of your application. There is no way to prevent this behavior.
It looks like you are positioning your view hierarchy in the first example starting at the point (0,20). Also, is that a UIToolbar or a UINavigationBar? If it's the latter, why are you using it by itself and not using it inside of UINavigationController?
If you do not use UINavigationController and are instead using custom view controller containers, you'll need to position your views accordingly.
See this answer for a thorough explanation.
I have similar UI design and based on Matt Hall answer and some article I've googled, I come up with something like this:
- (void)viewDidLoad {
[super viewDidLoad];
if (NSFoundationVersionNumber>NSFoundationVersionNumber_iOS_6_1) {
CGRect statusBarFrame = [self.view convertRect: [UIApplication sharedApplication].statusBarFrame fromView: nil];
UIToolbar *statusBarBackground = [[UIToolbar alloc] initWithFrame: statusBarFrame];
statusBarBackground.barStyle = self.navBar.barStyle;
statusBarBackground.translucent = self.navBar.translucent;
statusBarBackground.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
[self.view addSubview: statusBarBackground];
}
}
Where self.navBar points to navigation bar added in storyboard. This is needed only in case when it runs on iOS7 that is why I've added this condition (my app has to support iOS5).
This works like a charm.
alternative approach (enforce status bar size) is also good:
- (void)viewDidLoad {
[super viewDidLoad];
if (NSFoundationVersionNumber>NSFoundationVersionNumber_iOS_6_1) {
CGRect statusBarFrame = [self.view convertRect: [UIApplication sharedApplication].statusBarFrame fromView: nil];
self.navBar.frame = CGRectUnion(statusBarFrame, self.navBar.frame);
}
}
I've found another solution I think this is best since it involve only storyboard and no code is required.
Switch storyboard view to 6.1 mode (view as: iOS 6.1 and Earlier)
Select problematic UINavigationBar
in size section add 20 delta height in "iOS6/7 Deltas"
Switch back view to 7.0 mode (view as: iOS 7.0 and Later), and be happy with result.
when you embed view controller with navigation view controller that time you will see navigation bar to all the view controller you are pushing to from same view controller. In your first case you are adding the navigation bar object, insted of that you can select view controller from storyboard , go to attributes inspector tab & from their select Top bar as translucent navigation bar.

Resources