Our project runs for all iPAD's and we came across a problem as an example we have 8 buttons vertically sitting on a screen with constraints being added as vertical spacing they look fine on a iPAD 9.7 inch, but they look really big on iPAD 12.9, so the question is, is there any good way to actually use the screen space for something better, as in add an extra UIView if it is iPAD 12.9. I have looked into working with size classes, but I believe there is one size class for all iPADs, what I want is if there is a way to have different UI for different iPAD sizes using the Interface builder
-
Do you have any examples of UI you want to achieve? – Sviatoslav Yakymiv Jul 01 '17 at 19:01
-
Isn't this what StackView is supposed to do? Check it out.. – Sti Jul 05 '17 at 07:39
-
You don't need to add UIView, You can achieve your goal by set constraint in proper way.There are many option inside constraint to set view like Relation, Priority,Aspect ratio etc. – Shabbir Ahmad Jul 05 '17 at 10:56
6 Answers
The way I imagine your situation is that this specific ViewController has a lot of shared stuff, (like a common top bar, or a navigation bar) but just the middle content doesn't seem to fit properly.
In cases like this it is recommended to have a custom UIView that will load a different xib file based on the height or width of the current device.
The key point here is that, you actually only need one UIView subclass.
For this you can use @IBDesignable as well to preview it in real time inside the interface builder.
To achieve this you have to follow the next steps.
1) Create a .xib file for each of your "UIViews" based on the sizes.
2) Create an UIView subclass.
3) Hook the properties from the interface builder to this subclass. Note that you have to repeat this process for each of the xib files you want to use. IMPORTANT: Even though they are different xibs, they all get hooked into the same class.
4) Mark the created class as @IBDesignable like this.
@IBDesignable class CustomView: UIView {
...
}
5) Add the following code inside your class that will load a different xib based on whatever criteria you chose.
////////// View Logic //////////
// Our custom view from the XIB file
var view: UIView!
func xibSetup() {
view = loadViewFromNib()
// use bounds not frame or it'll be offset
view.frame = bounds
// Make the view stretch with containing view
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
// Adding custom subview on top of our view (over any custom drawing > see note below)
addSubview(view)
}
func setup()
{
// Extra setup goes here
}
func loadViewFromNib() -> UIView {
let bundle = Bundle(for: type(of: self))
let nib : UINib
let screenRect : CGRect = UIScreen.main.bounds;
// Use a different Nib based on the current screen height
if screenRect.size.height == 1024 {
// iPad Air & Pro
nib = UINib(nibName: "iPadNormal", bundle: bundle)
}
else if screenRect.size.height == 1366 {
// Large iPad Pro
nib = UINib(nibName: "iPadLarge", bundle: bundle)
}
else {
// Fall back
nib = UINib(nibName: "iPadFallback", bundle: bundle)
}
let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
return view
}
override init(frame: CGRect) {
// 1. setup any properties here
// 2. call super.init(frame:)
super.init(frame: frame)
// 3. Setup view from .xib file
xibSetup()
// 4. Other Setup
setup()
}
required init?(coder aDecoder: NSCoder) {
// 1. setup any properties here
// 2. call super.init(coder:)
super.init(coder: aDecoder)
// 3. Setup view from .xib file
xibSetup()
// 4. Other Setup
setup()
}
////////////////
IMPORTANT:
This approach is ONLY recommended when the contents of the custom view are the same, or with very minimal changes (layout doesn't matter). If the contents change a lot between sizes (like you actually wanna display different things) then you should create a "BaseViewController" with your shared logic, and make a subclass per iPad Size, so that each of them has it's own ViewController + Interface Builder Screen. Then just load the required screen just as if it was a completely different screen.

- 13,391
- 3
- 64
- 104
-
hey @Pochi , thanks a lot for the answer, this is a great way to use different views. but the one question I had is what if the view I am making using your way, and that view only takes a certain amount of the height? how would I do this instead of using let screenRect : CGRect = UIScreen.main.bounds. what happens if I don't give it a height? Also, can I use this UIView class in my storyboard? – Shabarinath Pabba Jul 05 '17 at 14:16
-
First question: Nothing happens, it will be displayed properly as long as it has proper constraints. You need to specify a position (like center x & y), plus the view's size. You don't really need to specify the height as long as all the elements within the view have relative position to each other. Just make sure the top element has its positioning relative to the top of the view, then the element beneath it relative to this last element, and so on until the last element has a position relative to the bottom of the view. The good part of this approach is that you can design it on the IB. – Pochi Jul 06 '17 at 00:40
-
Second question: Yes. If you use the code i posted above, just, drag a UIView into the interface builder. Then set it as a type of your custom view. It should automatically appear as a preview. But just keep in mind that, for the Interface Builder (IB) to render the view it uses the code inside the init?(coder aDecoder: NSCoder) method. And since that one is calling "loadViewFromNib" the conditions there will define which XIB is gonna be used as a preview. – Pochi Jul 06 '17 at 00:44
-
And before I forget, here's a post that describes how it works: (it's a bit old but not much has changed) http://supereasyapps.com/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6 – Pochi Jul 06 '17 at 00:46
Just put constraints as i suggested below Have a look on the Sample i have created for you.
- Give your Button Aspect ratio.
- Give width equal to the parent View's width.
- Add Constraint Center Horizontally in container and Center Vertically in container.
- Select Your Button and then go to size inspector and set the multiplier for the width (like 0.3 or 0.4 etc).
- Then set the multiplier for "align center X to.." (if you want your button to be left of center then set multiplier below 1 like 0.8, 0.7,0.5 etc And if you want your button to be in the right of the center then set the multiplier value bigger than 1 like 1.2 etc).
- Set the multiplier value for "Align center y to.." as like in Step 5.
Its all done.. Just run and check.
Hope this will help you.

- 583
- 5
- 16
You can use AutoLayout for this. You can assign aspect ratio base height to your buttons. Remember there is an option of setting ratio relationship to be 'equal to' or 'less than equal to.' You could use these instead of giving exact constraints. So this would cause button to adapt heights. Then in the code you could simply check if there is enough space remaining to draw an extra uiview or not. This will solve the 'Looking really big' problem also.
Check IB screenshot here to see what i am referring to: Click on 'Relation' to see these settings

- 465
- 5
- 14
Assume your nibs are Foo_pro.xib and Foo_ipad.xib.
@implementation Util
+(BOOL) isIpad_1024
{
if ([UIScreen mainScreen].bounds.size.height == 1024) {
return YES;
}
return NO;
}
+(BOOL) isIpadPro_1366
{
if ([UIScreen mainScreen].bounds.size.height == 1366) {
return YES;
}
return NO;
}
+(NSString *)convertXib:(NSString *)nibName {
if([Util isiPadPro_1366]) {
return [NSString stringWithFormat:@"%@_pro", nibName];
} else {
return [NSString stringWithFormat:@"%@_ipad", nibName];
}
}
Foo *foo = [[Foo alloc] initWithNibName:[Util convertXib:@"Foo"] bundle:nil]

- 3,841
- 8
- 21
Try This
1.Remove constrains from all of your buttons
- Add all of your buttons into a stackview
- Put vertical constrains on your stackview
- set same height same width for stackview buttons
- Remove height if you set for any button
- Don't set height for stackview if you want it to run on different devices.

- 51
- 11
You can use this
All buttons embeded into view and set to its constraints to superview.
- make sure add a aspect ratio constraints to it.
Select all buttons and add constraints
- Equal width ,Equal Height, Aspect ratio

- 876
- 7
- 28