Size class to identify iPhone 6 and iPhone 6 plus portrait
Asked Answered
D

10

19

How to uniquely identify iPhone 6 and iPhone 6 plus portrait screens using size classes?

My App looks good in iPhone 4 and iPhone 5 but the same looks with lots of empty spaces in iPhone 6 and 6 plus because of screen sizes. Though am using auto layout i can't increase the font size or view size only for iPhone 6 and 6 plus alone. I knew that we can change the font size and view size using size classes. but in my case don't know what to do.

Am using xCode 6.1 and my app supports from iOS 7 to latest iOS 8.1. Am expecting solution only in storyboards as am doing my UI designs fully in storyboard. If storyboard has limited functionality to achieve my needs please let me know how to achieve the same with code through out the app?

Delly answered 21/11, 2014 at 16:26 Comment(6)
It's all the same as far as size classes and device type are concerned. If you are doing auto layout correctly, view size will just change as the screen's proportions change. Can you show screen shots of why you need a different font size?Iceblink
@Iceblink you can see the file here for iPhone 6 plus. Due to NDA i cant share the real version. I just need gaps between each label and i do have some controls down . dropbox.com/s/ycar93s6j8djv33/…Delly
Thanks for the screen shot but what is it that you think is wrong with it?Iceblink
@Iceblink the requirement is to have same layout for all the screen sizes. So if the screen size increases then automatically my label size and label to text field gap needs to be increased. :( As of now the size is same as lower sizes.Delly
"the requirement is to have same layout for all the screen sizes" That's a dumb "requirement". The whole philosophy here is to adapt to the changing multiple screen sizes. That's why the WWDC videos on this topic are about adapting. Saying "the same layout" is the opposite of adapting. It is stodgy. :) If you don't want to adapt, then heck, include only a launch image for iPhone 4s and let yourself be zoomed up on the iPhone 6 models. You'll have exactly the same interface then.Iceblink
i knew it is the dumb requirement but my dumbest designer want that way :( between could you please elaborate more on the zooming up for iPhone 6 models. Or Can i go ahead and use diffent storyboard for iPhone 6 models alone?Delly
M
24

Another option to adjust the font size according to the iPhone type, is to use 'User Defined Runtime Attributes'.

Define an extension to UILabel:

extension UILabel {
    var adjustFontToRealIPhoneSize: Bool {
        set {
            if newValue {
                var currentFont = self.font
                var sizeScale: CGFloat = 1
                let model = UIDevice.CurrentDevice().modelName()

                if model == "iPhone 6" {
                    sizeScale = 1.3
                }
                else if model == "iPhone 6 Plus" {
                    sizeScale = 1.5
                }

                self.font = currentFont.fontWithSize(currentFont.pointSize * sizeScale)
            }
        }

        get {
            return false
        }
    }
}

In order to determine the current model name, please refer to the following answer: https://mcmap.net/q/44868/-how-to-determine-the-current-iphone-device-model

On the storyboard, select the label you wish to adjust, open the right pane, select the identity inspector, and add the 'adjustFontToRealIPhoneSize' property to the list of user defined runtime attributes (with type 'Boolean' and checkbox checked).

Do the same for each label you wish to adjust (copy & paste surprisingly works here).

Moiety answered 23/12, 2014 at 9:57 Comment(4)
You could add a @IBInspectable to that extension and then you can edit it directly from the Attributes Inspector.Anglicist
Can somebody provide its Objective-C Version?Westleigh
I don't think nailing exact models is the (even intended) way to go with for targeting multi size devices.Jeffers
String comparing to model names is not a good idea idea (to put it nicely). You should use size classes. Check for the size class in various dimensions to determine what size font to use. See my answer for an example.Sherburne
T
8

Use Compact width and Regular Height in storyboard

Use Compact width and Regular Height in storyboard

Add layout constraint of hight and width relative with super view by adding multiplier. Let's say you have image view which has size half the super view then add multiplier 0.5.

enter image description here

Thumbprint answered 21/11, 2014 at 16:33 Comment(6)
Could you please explain little bit more on multiplier or give some link to read about it please?Delly
As of now i have set the size class as you mentioned in the image. But for iPhone 6 plus my font looks too small.Delly
but my issues is with the font size and gap between other controls. Say i have a label and text field with a gap of 10. it looks good in smaller screens but in biggers screen it will like same so i can see lots of empty spaces. Is there any way to identify and change the font size and gap between controls?Delly
thanks for the answer. i have added a screen shot to the comments for my question. please see to it to understand my needs.Delly
Both the iPhone 6 and 6 Plus use Regular Height when in portrait mode so this will not differentiate between the these two devices. See developer.apple.com/library/ios/documentation/UserExperience/…Sherburne
@Jignesh - It works for me but partially. The image size decreases but how to manage the spacing between each image? How to reduce the spacing? Please let me knowTrypanosomiasis
C
2

Check out adjustsFontSizeToFitWidth @ UILabel Class Reference. This will allow you to do some nice adjustments based on the different devices.

label.adjustsFontSizeToFitWidth = YES;
Cheesewood answered 21/11, 2014 at 16:33 Comment(0)
K
2

I don't have too much idea of sizeClass for different font size in different iPhone devices but I figured out with this solution.

  1. Add this method to your utility class.
  2. Just pass your super view to this method, this method is recursive so if you pass self.view than all subviews are set.
  3. Change your font size as you need.
-(void)setAllFonts:(UIView *)view
{

CGFloat fontSizeDiff = 0.0;

if (IS_IPHONE_6)
{
    fontSizeDiff = 1;
}
else if (IS_IPHONE_6PLUS)
{
    fontSizeDiff = 2;
}

for (UIView *vw in [view subviews])
{
    if ([vw isKindOfClass:[UILabel class]] || [vw isKindOfClass:[UIButton class]])
    {
        if ([vw isKindOfClass:[UILabel class]])
        {
            UIFont *font = [(UILabel *)vw font];
            [(UILabel *)vw setFont:[UIFont fontWithName:font.fontName size:font.pointSize+fontSizeDiff]];
        }
        else
        {
            UIFont *font = [(UIButton *)vw titleLabel].font;
            [(UIButton *)vw titleLabel].font = [UIFont fontWithName:font.fontName size:font.pointSize+fontSizeDiff];
        }
    }
    else if ([vw isKindOfClass:[UIView class]] || [vw isKindOfClass:[UIScrollView class]])
    {
        [self setAllFonts:vw];
    }
}
}
Kinnikinnick answered 27/5, 2015 at 5:59 Comment(1)
"I don't have too much idea of sizeClass for different font size in different iPhone devices" ... this is where you should STOP, and learn how to use size classes instead of putting in a hack. How does this code handle iPhone 7, 8, iPad Pro, etc...?Sherburne
E
2

Swift Version of @iBhaviks answer :

func getFontScaleForDevice() -> CGFloat {
    var sizeScale = CGFloat(1.0)
    if DeviceType.IS_IPHONE_6 {
        sizeScale = 1.2
    } else if DeviceType.IS_IPHONE_6P {
        sizeScale = 1.4
    } else if DeviceType.IS_IPAD {
        sizeScale = 1.4
    }
    return sizeScale
}

func setAllFonts(targetView:UIView, scale:CGFloat) {
    for vw in targetView.subviews {
        if let vl = vw as? UILabel {
            vl.font = vl.font.fontWithSize(round(vl.font.pointSize * scale))
        } else if let vb = vw as? UIButton, vbl = vb.titleLabel {
            vbl.font = vbl.font.fontWithSize(vbl.font.pointSize * scale)
        } else if vw.subviews.count > 0 {
            setAllFonts(vw, scale: scale)
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    let sizeScale = getFontScaleForDevice()
    if sizeScale > CGFloat(1.0) {
        setAllFonts(view, scale: sizeScale)
    }
    view.layoutIfNeeded()
}
Evanne answered 13/2, 2016 at 0:14 Comment(1)
Please don't encourage comparison to specific models. This code will break within a year. Learn to properly use size classes like Apple intended.Sherburne
R
1

Maybe you could set the perfect font size for the big screens, and then set the Autoshrink to minimum font size with the perfect size for the small screens, in that way you can have a dynamic font size without coding.

You will have to set the constraints for the label to adjust its size with the screen size anyway.

Hope this help

Reiner answered 21/11, 2014 at 16:47 Comment(2)
But autoshrinking doesn't work if the text wraps (more than one lines).Iceblink
If is a multiline label, then probably the solution will need some code. If not, then I think this is a good optionBeauchamp
D
1

After struggling lot just found of something for my need so posting the same for the future readers.

  1. As of now there is no way to uniquely identify the iPhone 6 model portraits using Size classes. However you can use compact width and regular height to design for all iPhones portrait screens
  2. To change font size you have to identify which iPhone the app currently running on using code and set the font size based on the same
  3. For my requirement - same layout for all the screen sizes - use multiplier in widths and heights constrains. Check Jignesh answers for this question to know more about it.

EDIT 24-SEP-2015 I recently found a way to customize your size class by using UITraitColleection only for iPhone 6 plus so you don't need to write much of code. i hope this link will help someone in future.

Delly answered 29/11, 2014 at 14:45 Comment(1)
But if we also want to support landscape mode for iPhones, the way using UITraitColleection wouldn't help.Lousewort
F
1

Bit late to this but I needed a label that would scale up to any device and used this method.

Create a new subclass of UILabel and in the .h file put this…

#import <UIKit/UIKit.h>

IB_DESIGNABLE

@interface OTHD_ScalableLabel : UILabel

@property (nonatomic, assign) IBInspectable CGFloat fontScale;

@end

and in the .m file put this…

#import "OTHD_ScalableLabel.h"

@implementation OTHD_ScalableLabel

- (void) layoutSubviews
{
    [super layoutSubviews];

    if( self.fontScale < 0.1 || self.fontScale > 1.0 )      self.fontScale = 1.0;

    CGFloat height = CGRectGetHeight(self.bounds) * self.fontScale;

    if( height )        self.font = [UIFont fontWithName:self.font.fontName size:height];
}


@end

You can then just change your class in IB and using IBInspectable you will be able to scale the label up or down. Obviously, for the pedantics out there, this is not a good idea for general use but there are some cases where you might need, for example, a large label that displays full screen on an iPhone as well as full screen on an iPad.

Ferreby answered 3/10, 2015 at 16:45 Comment(0)
S
1

Here is an example of a function that I use to toggle between two different font size at runtime. It decides which font to use based on the horizontal size class - which essentially splits devices into two groups "iPad" and "iPhone". Here is a good refernce on whch devices belong to which size classes: http://useyourloaf.com/blog/size-classes/

  • iPad and Up
  • iPhone Plus and Down
 func chooseFont(compactFont: UIFont, regularFont: UIFont) -> UIFont {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    return appDelegate.window!.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact ? compactFont : regularFont
}
Sherburne answered 1/12, 2016 at 13:26 Comment(0)
I
0

Based on your screen shot I would suggest using Dynamic Type. That way the user is in charge of the size of the text.

Iceblink answered 21/11, 2014 at 17:2 Comment(2)
So you meant to say as a developer i don't need to care about the font size and gap between controls. So my app will look with lots of gaps in bigger screens and definitely it will affect the user experience.Delly
Why should there be "lots of gaps"? That is what auto layout takes care of.Iceblink

© 2022 - 2024 — McMap. All rights reserved.