Available screen height with UINavigationBar + UITabBar - ios

So I'm developing an app with a UINavigationBar on top, and a UITabBar on the bottom. And I'm having a hard time trying to figure out what is the real available height for the views.
I've tried calculating the available screen height by calculating the UINavigationBar height and UITabBar height and subtract it from the main screen height, but that is still not the real size.
Here's my failed code for obtaining the available screen height:
CGRect screenRect = [[UIScreen mainScreen] bounds];
_screenHeight = screenRect.size.height;
CGFloat tabBarHeight = _rootViewController.tabBar.frame.size.height;
UINavigationController* navigatior = _rootViewController.viewControllers[0];
CGFloat navigationBarHeight = navigatior.navigationBar.frame.size.height;
CGFloat visibleHeight = _screenHeight - navigationBarHeight - tabBarHeight;
return visibleHeight;
Is there a clean way to know the real available screen size in an UINavigationBar + UITabBar based app??

You don't need to calculate it and it changes depending on the iPhone. Your best bet and easiest path is to use the storyboard and embed both your navigation controller and tab bar directly in there. Once you have done that, you can use auto layout to pin your views to the bars and everything will be sized perfectly for you.

Related

iOS part of viewcontroller goes black when orientation changes

When I change viewcontroller orientation while it's loading on particular orientation, part of the screen goes blank at the bottom.
Steps to reproduce:
Have tableview(Not necessary I think. could be any view) in a view controller
Push a new viewcontroller which also has a tableview(Not necessary I think. could be any view) during
an action
Rotate the screen from one orientation to Another(Portrait to landscape or landscape to portrait).now you will be able to see the dark part.
Press back button to pop the current viewcontroller
Now rotate from one orientation to Another(Portrait to landscape or landscape to portrait).now you will be able to see the dark part here as well.
The bottom part of viewcontroller goes black.
I am able to reproduce 7 out of 10 times.
FYI:
My Viewcontroller has only tableview that's all and all cells has autolayout constraints.
Trying to understand why it happened and I would like to fix it.
More details on reproducing the issue:
Basically you can reproduce this issue only if you hold your device in slanting position and either push or pop a view controller and while the page is trying to load , you have to change the orientation then the issue happens.
(Pun intended.... lol )
In other words ,you have to tilt you device as if you are steering the wheel :).
This issue can only happen if you use your device like a steering wheel :)
In your viewWillTransition method call layoutIfNeeded()
Try to reset the layout of TableView after rotation by using this method,
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tableView.layoutIfNeeded()
}
or
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.layoutIfNeeded()
}
I also experienced the same issue.
My view controller had just one tableview and when we tilt , I mean change the orientation during a navigational push or pop this used to happen.
Try setting the frame
in viewDidLayoutSubviews
-(void)viewDidLayoutSubviews{
CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat width = CGRectGetWidth(screen);
CGFloat height = CGRectGetHeight(screen);
CGRect frame = self.tableView.frame;
// To check if there's any mismatch between the sizes of screen and tableview then set the tableview frame same as screen frame.
if (CGRectGetHeight(frame) != height && CGRectGetWidth(frame) != width) {
self.tableView.frame = CGRectMake(0, 0, width, height);
}
}
or try setting the frame in viewWillTransitionToSize
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat width = CGRectGetWidth(screen);
CGFloat height = CGRectGetHeight(screen);
CGRect frame = self.tableView.frame;
if (CGRectGetHeight(frame) != height && CGRectGetWidth(frame) != width) {
self.tableView.frame = CGRectMake(0, 0, width, height);
}
}
FYI:
if setting the frame self.tableView.frame = CGRectMake(0, 0, width, height); doesn't work then you could try [self.tableView layoutIfNeeded]
Set frame again in
viewDidLayoutSubviews
In one view controller(Parent the one that pushes new view controller) setting the frame at viewDidLayoutSubviews solves the issue in another view controller(The child view controller , one that's getting pushed) setting the frame at viewWillTransition fixes the problem :) But still I don't know why there's no universal solution to this problem.

How to access correct width value from IB with Autolayout

I have some strange Issues.
I have a UIViewController and only 1 UIView (I call it containerView) inside. The UIView should have the same Width as the UIViewController.
So I set the Leading and the Trailing Constraints between the UIView and the UIViewController to 0. During runtime everything works fine, BUT, how can I access the actual width during runtime? I tried it with:
self.containerView.frame.size.width
but of course frames doesn't work with autolayout and I only got a width of 600.0f, which is the standard width from the Interface Builder!
I also tried to set a fixed Constraint Width but this also makes no sense because the iPhone has a different Screen Width as the iPad for example.
Any Ideas how i can access the Width of my UIVIew during runtime.
PS: As you can see i use Interface Builder, Size Classes and Autolayout!
try to get the width in viewDidLayoutSubviews
-(void)viewDidLayoutSubviews
{
NSLog(#"%f", self.containerView.frame.size.width);
}
and since your UIView have 0 space to all screen edges the width of the UIView will be the same as the screen size so you can get it like this:
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;

Screen size minus advertising size

How can I get the screen height minus the height of the ads I'm displaying?
I get my screen size with
[[UIScreen mainScreen] bounds].size;
And I'm showing one banner ad:
self.canDisplayBannerAds = YES;
So the screen height should be something like:
[[UIScreen mainScreen] bounds].size.height - banner.height;
I want to place a object in the exact middle of the screen and the banner isn't showing all the time.
canDisplayBannerAds will show an ad that you can't adopt its delegate what so ever. Also you cant reference the ad view to get frame height or width. I suggest using old fashioned way. I can post a code if you want.
Getting the size of the screen isn't really what you want to do. This is because if the device turns sideways (if you are supporting rotation) or if your view controller does not take up the entire screen (like if your view controller is in a UINavigationController or UITabBarController) your banner will be off the screen.
To place the banner at the bottom of the viewControllers view and place an other view in the middle of a viewControllers view you could write something like this
-(void) viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
CGRect bounds = self.view.bounds; // for a normal view controller {0,0,width,height}
CGRect bannerRect = self.banner.frame;
bannerRect.origin.y = bounds.size.height - bannerRect.size.height; // bottom of the screen
bannerRect.origin.x = (bounds.size.width - bannerRect.size.width)/2.0; // centre horizontally
self.banner.frame = bannerRect;
CGRect objectRect = self.objectView.frame;
objectRect.origin.y = (bounds.size.height - objectRect.size.height)/2.0; // centre vertically
objectRect.origin.x = (bounds.size.width - objectRect.size.width)/2.0; // centre horizontally
self.objectView.frame = objectRect;
}

UIScrollView inner boundaries issue

So I have a strange bug in my code that is confusing me...
In the screenshot below, I have a UIScrollView. In the Storyboard, I set the background color to Red. Then using a bit of code, I set the boundaries so that there is a tiny gap between the title bar area and footer (The yellow slivers).
The problem is that when I scroll the scroll view All the "bottom", the scroll bar is not actually at the bottom of the UIScrollViews boundaries. This behavior is also mirrored when you scroll all the way to the top of the scrollview, and so it adds an ugly space to the top of the scrollview.
Is there some sort of separate bounds that I should set for the inner size of the scrollview?
Code:
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
CGRect screenRect = [[UIScreen mainScreen] bounds];
self.productScrollview.frame = CGRectMake(0, navBarHeight+22, screenRect.size.height, screenRect.size.width-footerHeight-navBarHeight-23);
self.productScrollview.contentSize = CGSizeMake(self.productScrollview.frame.size.height, self.productScrollview.frame.size.width);
self.productScrollview.contentSize =CGSizeMake(screenRect.size.width, 700);

UIPickerView animated on bottom for both retina 3.5 and 4

Have an UIScrollView (mainScrollView) that is 838 pt height, so it's bigger than both retina 3.5 and retina 4 displays height, and the user can so scroll it down to see all content.
Want to display an animated UIPickerView from the bottom, and it should stay always on the bottom of the screen, independent of screen height (retina 3.5 or 4) or mainScrollView (838 pt) height.
Is there a way to get the "window" or "screen" height and add UIPickerView considering the measures for the different screens? What should be the correct approach to accomplish this?
This will return the frame of screen
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
With this you can position your picker accordingly !!!

Resources