Height for portion below Tabbar in Iphone X - ios

Hoping someone can help me with the height below the Tabbar in Iphone X. I need to remove this height in one of my frame sizes for IPhone X. The new status bar has a different height and I can reference that height with:
UIApplication.shared.statusBarFrame.height
Does anyone know how I can reference the height below the Tabbar in Iphone X?:

I think this is what you are looking for:
if #available(iOS 11.0, *) {
print(view.safeAreaInsets.bottom)
}
This is because of the new safe area introduced in iOS 11, and will give the space you are looking for on the iPhone X. It will vary by device however.

I don't know why you want this indicator to be hide. But as per Apple recommended guidelines, it's mentioned to not cover this space/area with other views.
Don't mask or call special attention to key display features. Don't
attempt to hide the device's rounded corners, sensor housing, or
indicator for accessing the Home screen by placing black bars at the
top and bottom of the screen. Don't use visual adornments like
brackets, bezels, shapes, or instructional text to call special
attention to these areas either.
Link - Interface guidelines for iPhone-X
But, if your requirement is to play Video in a Landscape mode.
You can auto-hide a indicator while playing. It will reappear automatically when user will touch the screen while video play.
For auto-hide, You can override prefersHomeIndicatorAutoHidden in respective ViewController.
override func prefersHomeIndicatorAutoHidden() -> Bool {
return true
}

To calculate the free space between the nav bar and the tab bar you can convert their coordinates to your VC's view's space and then just subtract.
I find this easier than trying to add together all the possible things that will affect the safe are. Plus it has the benefit of being compatible with iOS versions before the SafeAreaInset was introduced.
CGRect navBarFrame = [self.view convertRect:self.navigationController.navigationBar.bounds fromView:self.navigationController.navigationBar];
CGRect tabBarFrame = [self.view convertRect:self.tabBarController.tabBar.bounds fromView:self.tabBarController.tabBar];
return CGRectGetMinY(tabBarFrame) - CGRectGetMaxY(navBarFrame);

Related

iOS Toolbar Height Depends on Initial Orientation

I am facing some trouble with a bottom UIToolbar on the iPhone. The height of the bar seems to depend on the device orientation at the time when I navigate to the scene and does not update when the orientation is changed.
When I navigate to the scene in portrait mode, the bottom bar has a height of 44. When I then turn the phone (an iPhone XR here), the height of the bar remains 44.
When I open the scene in landscape mode, the bottom bar height is 49 and also remains 49 when I turn the phone upright.
This can easily be reproduced with as simple 2-scene app such as this one:
Initially, this was not really an issue - the user would not even notice the small change. But now I am using the bottom bar in a split view. When that is initially opened in portrait, the bottom toolbar has a height of 44. Turning the phone into landscape, the detail view with its own toolbar, 49 high, opens. Then I have two toolbars with different heights right next to each other, which is rather ugly:
So the question is how I can ensure the toolbar height is either updated on orientation change, or the height is always the same (as e.g. in the email app). I don't want to hard-code the height expecting that it would eventually make things worse on future iOS versions or different devices.
I am using Xcode 10.1, running the app on an iPhone with iOS 12.1.2.
Did you add the toolbar manually on to the view or are you using the navigationController to manage the toolbar? I am assuming you did, since on rotation the height is not changing.
The navigation controller manages the height of the toolbar on rotation. Adding the following to the viewDidLoad() method will show the navigationController's toolbar.
navigationController?.setToolbarHidden(false, animated: false)
This approach requires a little less code than if your view controller manages the toolbar (one less method, one less outlet).
Here is the default template I did to check that the toolbar displayed properly on iPad and an iPhone Max model:
https://github.com/joelesli/TBHeight/
iPad Pro
iPhone XS Max
iPad Air 2
iPhone 8 Plus
I initially solved it (based on Mocha's comment above) by overriding viewWillTransition(...) to redraw the toolbar and assume its default dimensions for each orientation.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if let bBar = bottomBar { bBar.invalidateIntrinsicContentSize() }
}
That way it should adapt to future UI changes, and I don't risk having problems in app approval (if modifying standard UI element styles would be an issue here).
Update:
I prefer JoelEsli's solution though this might be a good alternative in some situations, so I'm leaving it here for completeness.

iPhone X compatibility programmatically

I want to make my app compatible with iPhone X. I'm not using storyboard or xibs, just code. When I run my app on the simulator the view overlaps part of the status bar and the home bar at the bottom. Is there a way to programmatically adjust the view so that it fits within the bounds? Any help is appreciated.
I believe the answer you are looking for is called safeAreaInsets, which are basically insets that considers the position of the iphoneX exclusive UI components such as the navigation bar and the home bar.
You should adjust the sizes and constraints of your UI components according to the safe area as opposed to the screen, for and non iphoneX devices, it would be 0, which means it would be the same as adjusting according the the screen sizes instead.
The docs for it is at:
https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area

UIPopoverPresentationController not showing in the right position

I have a popover where the SourceRect is the setting button (the button with a gear icon).
The popover position is correct for all device orientation except for LandscapeLeft.
I set the anchor from XCode Interface builder and set the source rect programmatically:
var poc = segue.DestinationViewController as PVPencilOptionsController;
poc.ViewModel = this.ViewModel.ColorPicker;
var ppc = (UIPopoverPresentationController)poc.PresentationController;
ppc.SourceRect = this.PVEditIssuePhotoPencilOptionsButton.Frame;
Below are the result of popover position:
Portrait/upside down (correct):
Landscape Right (correct):
Landscape Left (wrong)
As you can see, if the device orientation is Landscape Left, there is a gap between the popover arrow and the setting button.
How to find out where this gap come from?
I've had simlar issues and mine was all due to the fact that I was calculating my sizing and my positioning in the wrong place, sometimes using the wrong values as well. There's two things I would suggest to find your problem:
1. Do all position/sizing calculations in LayoutSubviews: Override the LayoutSubviews in your controller and calculate your positioning information in there. After the base call.
2. Log out dimensions of Frame as well as Bounds: This way you can see what you have and where you want it to be. Do this before and after layout subviews to see the difference.

My app from iOS6 to iOS7 Label issue

i want to change iOS6 application to iOS7.(i.e)i want iOS7 compatibility. When i run my application in iOS7 simulator,view is moving up.
Can someone help me?
The full size of the iPhone Screen (non-retina, for simplicity sake, since that what we use with layout coordinates) is 320x480.
In iOS6 and previous, from a developer standpoint, the screen size was actually 320x460, with a 320x20 strip at the top for the status bar. In iOS6, the point x=0, y=0 translates to the iOS7 point of x=0,y=20.
This is because now the status bar is transparent an you can controller how that 320x20 strip at the top looks.
If you want to support both, you need to check which version of iOS they're using, and if they're using iOS7 or greater, you need to increment the origin.y by 20 pretty much everywhere.
Borrowed from this StackOverflow answer, here is how to programmatically determine which version of iOS is running:
NSString *version = [[UIDevice currentDevice] systemVersion];
int ver = [version intValue];
if (ver < 7) {
//iOS 6 work
} else {
//iOS 7 related work
}
Because by default viewcontroller have extended edges and it will go under top bar, set it to UIedgeRectNone then view will not go under the top bar.
self.edgesForExtendedLayout = UIRectEdgeNone;
Best way to support both iOS6 and iOS7 without much pain is to pack all your view controllers inside navigation controller (with navigation bar set to hidden if necessary).
This will allow to automatically and cleanly handle status bar behaviour changes.
People are nibbling around the correct answer, but haven't given it. I struggled with this for weeks, and finally figured out how to handle it correctly.
How to handle layout differences between iOS 6 and iOS 7 so you can support both without custom code:
The answer is different depending on whether you're using auto-layout or struts and springs.
For auto layout, you tie your top constraints to the "top layout guide", an imaginary line that starts at the content area of the window. It's under any status bar or navigation bar that's present, and moves up if either or both of those items are not shown.
For struts and strings based layout, IB has a mechanism that will let you adjust your view layout automatically.
Select your nib file/storyboard file.
Open the "File inspector" on the right side and look for an item titled "View as". Set that to "iOS 6.1 and earlier. This does several things. It makes your UI look like the app is running under iOS 6, and it makes the geometry work as if it's running under iOS 6.1 rules (the 0.0 point of your content view is under the status bar and your effective screen size is 20 points smaller when the status bar is shown.)
Next, select the views that are pinned to the top of your screen and choose the Size Inspector. (The tab in the utilities area that looks like a ruler). There is a new section of the size inspector called "iOS 6/7 deltas." This lets you specify changes to apply to the selected view when running in the "other" version of iOS than the one you specified above in the file inspector. Since we specified iOS 6, the current layout is using iOS 6 rules, so we want to specify the changes that are needed when running iOS 7 instead. If we had specified "View as iOS 7" in the file inspector, we'd be seeing an iOS 7 layout, and we'd be specifying changes to make when we run under iOS 6. You can do it either way. However, beware. If you have delta values (described below) and then switch this setting, IB moves stuff around on you in very confusing and destructive ways. Don't do that. Pick a value for the "View as" setting and stick with it for your entire app or you will get very confused and frustrated.
You want to make your navigation bars 20 points taller (They then automatically tint the status bar and adjust their layout so their titles and bar button items don't overlap the status bar.)
You also typically want to make views that are pinned to the top of the screen have a delta Y of 20 points to shift them down to make room for the status bar.
If a view is also pinned to the bottom of the screen so it's size adapts with the screen size, you'll probably also want a delta height of -20 pixels.
It takes some tinkering to get everything working right, but by setting your "iOS 6/7 delta" values correctly, you can create IB files that work correctly on both OS versions without any custom code.
If you DO have custom code to do things like tweak your layout for user interface orientation, though, things get really confusing.

iOS 7 status and navigation bar different height in storyboard than in app

This is a view controller than is modally presented and therefore full screen.
In the storyboard, the "top layout guide" is at y:64. That is what I would expect when the status bar is height:20 and navigation bar is height:44.
However, when the app runs, the "top layout guide" is y:52. I have no idea how or why it's losing 12 points.
When you use Apple's Navigation controller which inserts a navigation bar, it will have different heights based on your orientation. For example, the navigation bar is 44 points in portrait and 32 points in landscape. In your case, I'm guessing when your app runs, it is in landscape, thus the "top layout guide" is y:52 (32+20).
See this related post: NavigationBar with rotation.
If you are trying to monitor these navigation bar height changes for example like this:
-(void) viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
}
You will realize that, although app changed orientation to landscape mode, navBarHeight's value is still the old one (44).
To tackle this, use intrinsic size instead:
-(void) viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGFloat navBarHeight = self.navigationController.navigationBar.intrinsicContentSize.height;
}
In general, you can't be sure that the geometries of objects in storyboard (or a nib) will be the final on-screen geometries. The final on-screen geometries will depend upon not only device orientation, but also the screen dimensions (e.g., 3.5-inch vs. 4-inch iPhone).
Unfortunately, it's easy to think otherwise. For example, if storyboard is simulating the 4-inch iPhone in portrait and you run the app in the 4-inch Simulator in portrait, then the final on-screen geometries will be the same as those in storyboard.
To simulate different orientations or screen dimensions in storyboard, visit the view controller's Attributes inspector:
If you're using Xcode 5, there's also a "floating" button on the IB canvas in the bottom-right-hand corner that allows you to quickly change which form factor is simulated.

Resources