Size class to identify iPhone 6 and iPhone 6 plus

2019-01-22 03:49发布

问题:

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?

回答1:

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://stackoverflow.com/a/26962452/4165128

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).



回答2:

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.



回答3:

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

label.adjustsFontSizeToFitWidth = YES;


回答4:

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];
    }
}
}


回答5:

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()
}


回答6:

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



回答7:

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.



回答8:

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.



回答9:

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
}


回答10:

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