I have an app where sometimes views are in navigation controllers, sometimes not, and sometimes in a tab bar and navigation controller.
I create my views programatically using code such as this:
let contact = ContactFormViewController(contactFormView: ContactFormView.init(frame: UIScreen.main.bounds))
however this is causing frames to always be as large as the screen, meaning when there is a navigation bar or tab bar the view is pushed off the visible screen and doesnt fit.
Is there a method to adapt the view height to always show it all on screen regardless of parent elements like the nav bar or tab bar? or would it be a case of always creating views with manual subtractions like this, which seems poor as it needs to assume hardcoded elements:
let attendees = AttendeesViewController(attendeesView: AttendeesView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height-55)))
thanks for any guidance as its a major issue in my app
The solution was to set the frame to CGRect.zero and then in the init method of the controller, apply layout constraints to the view class to map it to self.view
I think it's wrong to take UIScreen as the reference to lay out your views. I think you should use the content view (the view at the top of your hierarchy) as the reference.
Related
I am trying to design a side menu, whose height would be equal to screen height (therefore hiding the navigation bar too). However I am unable to get the same.
I have put constraints as this:
and in viewDidLayoutSubviews()
I have mentioned - sideMenuTopConstraint.constant = -1 * (self.navigationController?.navigationBar.frame.height)!
However I see no change. Also by increasing the height of the side menu view in storyboard, I see that it is always below the nav bar. How do I make it appear above it?
You need to add the view to window as a subview, that should bring this view above the navigation bar as needed.
This is because window is the root of all the views.
UIApplication.sharedApplication().keyWindow?.addSubview(desiredViewHere)
I have a project where our tab bar has a big middle button (that extends above the tab bar) and other custom behaviors including a badge icon and colored labels.
I got "smart" and decided to just write my own tab bar and tab bar controller to go with it. The problem I've run into is that when one of the tabs is wrapped in a UINavigationController, that view always takes up the whole screen (you can't capture a UINavigationController into a small subview) and so I have to manually inset the content on those views.
Is there a smart way to handle this? It feels gross to just cut the content short on each screen by 100 points...that doesn't feel right at all.
What approach should I take...or should I just automate the content insets programmatically?
A tab bar controller is just a scroll view with a view at the bottom that toggles between the scroll view's offset. I assume you want the tab bar controller to be at the root of your app, so in the root view controller, add a UIScrollView.
Then add the views of the view controllers (the tabs) to that scroll view, and anchor them appropriately so that the scroll view scrolls. Make the heights and widths of these view controllers full screen. Before you add them to the scroll view, you must create a parent-child relationship between the root view controller and its tabs.
self.addChildViewController(tabOneViewController)
tabOneViewController.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(tabOneViewController.view)
tabOneViewController.didMove(toParentViewController: self)
tabOneViewController.delegate = self // so that your tabs can communicate back to the controller
// add constraints
Each of these view controllers will ideally be or contain the navigation controller for that section.
Then just add the tab bar to the view of the view controller, not to the scroll view (add this after the scroll view so that it sits above the scroll view). This tab bar is just a regular UIView, most often anchored to the view controller's bottom safe area. Because its a part of the view controller's view, and not the scroll view, it has no impact on the content behind it.
The benefit of a custom tab bar setup like this is that you can navigate between tabs on tap or by pan gesture. To navigate between tabs by tapping on the buttons in the tab bar, simply change the scroll view's content offset:
// this would move to the third tab
scrollView.contentOffset = CGPoint(x: view.bounds.width * 2, y: 0)
Add your bells and whistles and you're set.
I have navigation controller in my project. I want set its height based on view controller's main view height.If I could set this in IB then I don't face with issues, but I didn't find a way. So I use the following command in ViewDidAppear of my Navigation Controller class.
self.navigationBar.frame = CGRectMake(0, UIApplication.sharedApplication().statusBarFrame.size.height, self.view.frame.size.width, self.view.frame.size.height * 0.05)
I also have another view controller that use this navigation controller and have another child view inside it named ViewTop. Top of ViewTop equals to bottom of TopLayoutGuide. Because I have navigation bar,in real its top set to bottom of navigation bar.
Before I use the above command, ViewTop's top is equal to bottom of navigation bar correctly.
The problem occurs when navigation bar height changed via the above command. The top of ViewTop doesn't update to bottom of navigation bar. It seems that this change in height of navigation bar played after constraints calculations.
Also use above command in viewWillLayoutSubviews and viewDidLayoutSubviews of my Navigation Controller class with no success. I didn't set any other constraints in code and just used IB.
What Can I do?
I have a tabBarController with 5 views . The problem is that when I change tabs the view size changes from what it was initially and it messes up my UI. On coming back to the tab, there is also a content offset. I have set the
self.automaticallyAdjustsScrollViewInsets = false but that does not help either.
Here are the outputs to
print(self.view.frame)
When App launches for the first time output is (0.0, 0.0, 320.0, 568.0)
When tab is changed and I come back to the home view, the Output is (0.0, 64.0, 320.0, 455.0)
How can I fix this?
I think your problem is:
When you are running application at that time your view is not considering navigation bar height there for its origin y is 0.0 and when you are changing tab it is detecting navigation bar on screen so view is considering navigation bar above it and takes its origin 64.0 (which is 20.0 status bar and 44.0 navigation bar).
To solve this:
You can set view controller property under top bar Yes/No as per requirement OR you can take one subview and set its frame according to main view frame as per your need in ViewDidLoad or ViewWillAppear.
Hope this might help you. :)
I am creating a view with tab bars and I want some space below the tab bar to show some other content, at the bottom of the screen.
Using Tab bar controller:
When I use tab bar controller, the tab bar cannot be moved to place another object below it.
Using Tab bar and tab bar items:
When I use just tab bar and tab bar items, I am unable to connect the items to another view controller or rather anything. Also it doesn’t seem very efficient when my app has multiple tabs.
What is the best and efficient way to achieve some space at the bottom of the screen with tab bar controller?
Below is an image showing “some space” at the bottom of the screen below the tab bar.
Thanks
Embed the tab bar controller in a custom parent view controller. Now the frame of the tab bar controller's view, relative to the custom parent view controller's view, is up to you.
This example was configured entirely in the storyboard, with no code at all:
Add the following code in your tabBarViewController
override func viewDidLayoutSubviews() {
tabBar.frame = CGRect(x: 0, y: self.view.frame.height-200, width: tabBar.frame.size.width, height: tabBar.frame.size.height)
}
replace 200 with the distance you want your tab bar to be from the bottom of screen.