How to prevent UINavigationBar from covering top of view in iOS 7? - ios

After updating to Xcode 5, the navigation bars in all of my app's views have shifted down. Here are some screenshots, the first showing everything in the view as it's pulled down, and the second showing all of it untouched. The search bar should begin where the navigation bar.
Anyone know how I can fix this?
edit: i have tried this previously recommendation:
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
But it yields very odd results.
This may be because I have a "slide menu" under this view controller that is appearing due to the transparency of the navigation bar.

Set the navigation bar's translucent property to NO:
self.navigationController.navigationBar.translucent = NO;
This will fix the view from being framed underneath the navigation bar and status bar.
If you have to show and hide the navigation bar, then use
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
in your viewDidLoad method.

In iOS 7 by defaults all Controller translucent property value is YES, so you set translucent property NO for this issue.
self.navController.navigationBar.translucent = NO;

You can disable
the "Extend edges" in Attribute inspector of View Controller of this screen (as shown in below image)
:

This works for swift as well on iOS 8.1
navigationController?.navigationBar.translucent = false

If you want to keep the translucency on your navigationBar, at the end of your viewDidLoad or in your viewWillAppear add this line of code:
[self.view sendSubviewToBack:self.tableView]
Somehow if your scrollView subclass (UITableView, UICollectionView, etc.) is at index 0 in your current view subviews, it will automatically adjust the insets according to your navigationBar. And it shouldn't affect your UI in versions prior to iOS7 either.
EDIT
If you initialize your UITableView programmatically, then it is best to add it to the view using this [self.view insertSubview:self.tableView atIndex:0];

Swift 4:
Set following line of code in viewDidLoad method:
self.navigationController?.navigationBar.isTranslucent = false

You can add this method into your view controller as shown on this URL:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.searchBar.frame =
CGRectMake(0, self.topOfViewOffset, self.searchBar.frame.size.width, self.searchBar.frame.size.height);
}

Another approach is to set self.automaticallyAdjustsScrollViewInsets = YES; on your view controller.
This is enabled by default. But in your case:
I see you are using EGORefreshHeaderView. It plays with contentInset of UITableView. So when you release it, header will reset top inset instead of restore previous value.

If you want to have complete control on views and avoid faulty adjustments of iOS, subclass UITableView and adjust the insets (both scroll and indicators) in -(void)willMoveToWindow:(UIWindow *)newWindow. Works for me.

Another option is to open your Info.plist file in source code mode and enter the following info:
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIStatusBarHidden</key>
<true/>
Hope this helps.

Related

iOS 7 Height of TableView increase Under TabBar

Im trying port my app to iOS7, but the height of my TableView increases in ios 7 while it is correct in ios 6. Due to which last row (cell) is almost half under the tab bar.
Im searching a lot for it, but i dont find any solution. Can anyone help me?
Have a look at iOS 7 UI Transition Guide
if ([self respondsToSelector:#selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
Use edgesForExtendedLayout to specify which edges of a view should be extended, regardless of bar translucency. By default, the value of this property is UIRectEdgeAll.
if ([self respondsToSelector:#selector(extendedLayoutIncludesOpaqueBars)]) {
self.extendedLayoutIncludesOpaqueBars = NO;
}
If your design uses opaque bars, refine edgesForExtendedLayout by also setting the extendedLayoutIncludesOpaqueBars property to NO.
if ([self respondsToSelector:#selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
If you don’t want a scroll view’s content insets to be automatically adjusted, set automaticallyAdjustsScrollViewInsets to NO.
You can also set topLayoutGuide and bottomLayoutGuide. They indicate the location of the top or bottom bar edges in a view controller’s view. If bars should overlap the top or bottom of a view, you can use Interface Builder to position the view relative to the bar by creating constraints to the bottom of topLayoutGuide or to the top of bottomLayoutGuide.
Moreover, you can also make adjustments in Interface builder.
And if you are not using autolayout, you can set the deltas for iOS6/7.
Open Storyboard, in Utilities of your UIViewController open "Attributes inspector"
"Under Top Bars" is ticked?

When hiding the statusbar my navigation bar moves up in iOS7

I am trying to hide the statusbar but maintain the "bigger" navigationbar height. Right now when I hide the statusbar by setting - (BOOL)prefersStatusBarHidden to YES and then calling [self setNeedsStatusBarAppearanceUpdate];. The problem with this is that the navigationbar will slide up and won't leave space for the notification I'm trying to show. Simply adding a view over the statusbar is not an option, our statusbar/navigation has the fancy blur effect. Does anyone have a clue how to maintain the standard navigationbar height with the status bar height and remove the statusbar from that?
Edit; what I ended up doing is taking a risk and getting the UIWindow of the statusbar via a private API and offsetting that.
Edit 2; App got approved with the private API. Be cautious though!
You can create a custom UIView with its frame as
customView.frame=CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height);
Also hide your status bar by following the below steps
Go to info.plist and add two attributes if not present. set "Status bar is initially hidden" to YES and set UIViewControllerBasedStatusBarAppearance to NO. This will hide status bar for your app.
Add this code in your view Controller:
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)])
{
self.edgesForExtendedLayout = UIRectEdgeNone;
}
You should use of positionForBar: method of UIBarPositioningDelegate Protocol.
I don't want to put another answer or copy/past so you should take closer look at following question\answers. :)
iOS 7 Status Bar Collides With NavigationBar
iOS 7 UIToolBar Overriding With Status Bar
statusbar overlapping content in iOS7
I had to do this once. I ended up creating a custom navigationBar of my own and then just set the frame as:
navBar.frame=CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height);
It worked for me at the time. Just try it out.
Another workaround here: subclass UINavigationController override method:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (self.navigationBar.frameMinY < 1) {
self.navigationBar.frameHeight = 64;
} else {
self.navigationBar.frameHeight = 44;
}
}
in which set frameMinY is set frame.origin.y and set frameHeight is set frame.size.height

iOS 7 Custom TableView Is Under TabBar

Im trying port my app to iOS7, but my custom TableViewController is showing the last row (cell) under the TabBar :(
Im searching a lot for it, but i dont find any solution. Can anyone help me?
My Custom Table View class
The error is shown in the blow screenshot (only is showing a part of last product because im draging to up to show the hidden product under the tabbar):
Thanks.
I've got the same problem and solved it using storyboard.
At Tab Bar Controller, go to attribute inspector, Simulated Metrics, and set the Bottom Bar to Opaque Tab Bar. That's it!
See image bellow for description.
Saudações! (Greetings!)
I found the answer to your question on another post, answered by dariaa, here:
Tab Bar covers TableView cells in iOS7
It worked great for me.
Please no credit for me, because I'm not the original guy who solved it.
In your custom TableViewController, add these two lines under [super viewDidLoad]:
- (void)viewDidLoad
{
[super viewDidLoad];
self.edgesForExtendedLayout = UIRectEdgeAll;
self.tableView.contentInset = UIEdgeInsetsMake(0., 0., CGRectGetHeight(self.tabBarController.tabBar.frame), 0);
}
My friends, I cannot tell you how badly I struggled from this. Not a single re-configuration of Story Board never helped me. The issue was exactly like in Original Post, I've managed to fix it using:
for swift 3
self.edgesForExtendedLayout = []
for objective-c
self.edgesForExtendedLayout = NO;
2 lines in viewDidLoad and that's it !
self.edgesForExtendedLayout = UIRectEdgeAll;
self.tableview.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, CGRectGetHeight(self.tabBarController.tabBar.frame), 0.0f);
In iOS 7 viewController uses full height. There is a property introduced as
self.automaticallyAdjustsScrollViewInsets = NO;
set it to no. then check, or set UIEdgeInset if is not set right after it.
UIEdgeInsetsMake(top, left, bottom, right)
See here
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/AppearanceCustomization.html
Edit: try also this
self.edgesForExtendedLayout = UIRectEdgeNone;
The root cause of this problem is that automaticallyAdjustsScrollViewInsets is effective only on the First scroll view in your VC's view Hierarchy. It is not documented by Apple, but it is the only way the VC will detect the scroll view needing to be modified unless you're using a UITableViewController.
So in order to fix your issue without manually adjusting the insets, do this:
Make sure "Adjust Scroll View Insets" is checked.
Make sure that the tableView is the first subview in the view Hierarchy.
(Move it upwards above all other elements)
UIViewController has two new properties to assist you : topLayoutGuide and bottomLayoutGuide. They return the height of the parent view controller's controls you need to avoid. In this case, bottomLayoutGuide will return the offset of the tab bar.
Your custom view controller is probably overriding a method and not invoking super's implementation where this would be done for you. I am guessing you are installing AutoLayout constraints or setting a view's frame manually to fill the view. You just need to include the value from [bottomLayoutGuide length] to your layout calculation. If you support rotation, you should update that value in willAnimateRotationToInterfaceOrientation:duration:.
UINavigationController and UITabBarController both have a transparency flag that can be set programmatically or in the storyboard.
The UINavigationController also has two flags that control if the content extends under the top or bottom bar. Again you can set them programmatically or in the storyboard. This will apply to all subviews.
Each UIViewController can set its own preference in code. The property is called edgesForExtendedLayout and you can set up all combinations.
Using those properties will allow AutoLayout and Springs'n'Struts to adjust the views the way you want them regardless of the device.
There are a lot more new properties in UIViewController that you will want to have a look at.
Try the following:
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeBottom;
I've got the same problem. One solution to it is to make the ToolBar not Translucent. Here's how to do it:
First select the tool bar from the document viewer
like here
Then uncheck Translucent like here
Hope this helps.
Thanks.
The problem was masked using:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 112, 0);
}
But it doesn't solve, because on each iPhone and on each app tableview i have a different space on bottom.
So this is a poor solution.
I dont know a way to solve it.
I solved my problem now, changing my BaseTableViewController to inherit from UIViewController to UITableViewController.
But using a TableView inside a UIViewController is not solved :(
Thanks.
maybe is not a right answer, also for that reason I post this answer so you can tell me if this answer could be a possible solution.
In my case, I like the translucent effect, so I have added a footer in the table and I have modified the scrollIndicators.
- (void)viewDidLoad
{
// Do any additional setup after loading the view.
[super viewDidLoad];
UIView *footer = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.agendaItemsTable.frame.size.width, self.tabBarController.tabBar.frame.size.height)];
self.agendaItemsTable.tableFooterView = footer;
self.agendaItemsTable.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.frame.size.height, 0);
}
What do you think?
I had the same problem, and the up-voted answers did not solve it. See my answer to a similar question, Tab Bar covers TableView cells in iOS7.
I solved the issue by manually setting the table view's frame in the table view controller's viewWillAppear: method to the height of the screen - (status bar height + nav bar height + tab bar height).
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Adjust height of tableview (does not resize correctly in iOS 7)
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height = [self heightForTableView];
self.tableView.frame = tableViewFrame;
}
- (CGFloat)heightForTableView
{
return CGRectGetHeight([[UIScreen mainScreen] bounds]) -
(CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame]) +
CGRectGetHeight(self.navigationController.navigationBar.frame) +
CGRectGetHeight(self.tabBarController.tabBar.frame));
}
If anyone finds a better solution to this problem, please share!
For those like xarly who want the translucent effect, and for an Autolayout solution (without setting frames), see my answer here https://stackoverflow.com/a/26419986/1158074
I had a similar problem with collection view. Changing the collection view frame and content inset below fixed it for me...
guard let cv = collectionView,
let tabBar = tabBarController?.tabBar else { return }
// Resize collection view for tab bar
let adjustedFrame = CGRect(origin: cv.frame.origin,
size: CGSize(width: cv.frame.width, height: cv.frame.height - tabBar.frame.height))
cv.frame = adjustedFrame
// Adjust content inset for tab bar
let adjustedContentInsets = UIEdgeInsetsMake(0, 0, tabBar.frame.height, 0)
cv.contentInset = adjustedContentInsets
cv.scrollIndicatorInsets = adjustedContentInsets
Good luck!

UINavigationBar appearing as semi-translucent instead of opaque white

This is in an app I'm converting from iOS 6. Initially the ViewController was showing up under iOS 7 with the content of the main view underneath the navigation bar.
In the UI builder view, I turned off "Under Top Bars" and "Under Bottom Bars" in the "Extend Edges" section, to solve that issue. This worked, however, now on this screen the navigation bar appears to be translucent (comes across as grey in the screenshot below).
I've tried explicitly setting "Top Bar" to "Opaque Navigation Bar" under "Simulated Metrics," but this has no effect.
I've tried setting:
self.navigationController.navigationBar.translucent = NO;
in my ViewController's init code, but this also has no effect.
What am I missing?
UPDATE: If I set self.navigationController.navigationBar.translucent = NO; in my first ViewController in the stack, it works. However, prior to the ViewController in question, I do want translucent navbar. It's only when I get to a view several layers deep that I want to have a non-translucent bar (this view has no scrollable data, so it doesn't make sense to have it translucent).
Here's a screenshot of what I'm seeing in the nav bar:
The issue was that I was calling
self.navigationController.navigationBar.translucent = NO;
after my view appeared. I moved that code into my viewWillAppear method, and now it appears correctly:
You can try below code...
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
self.navigationController.navigationBar.translucent = NO;
And Add this code in View viewDidLayoutSubviews function...
You can set it across the board with an app using this:
UINavigationBar.appearance().navigationBarAppearace.translucent = false
I tend to do it in my AppDelegate class when the app initially loads up.
all you need to do for iOS6 is to set the controller's fullscreenlayout to NO and then PUSH it to your NavigationController
[controller setWantsFullScreenLayout:NO];

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