尺寸类别以识别iPhone 6和iPhone 6 Plus的竖屏模式。

19
如何使用Size Classes唯一识别 iPhone 6 和iPhone 6 Plus的竖屏屏幕?
我的应用在iPhone 4和iPhone 5上看起来很好,但由于屏幕尺寸问题,在iPhone 6和6 Plus上会出现很多空白。虽然我正在使用自动布局,但无法仅针对iPhone 6和6 Plus增加字体大小或视图大小。我知道可以使用Size Classes更改字体大小和视图大小,但在我的情况下不知道该怎么做。
我正在使用xCode 6.1,并支持从iOS 7到最新的iOS 8.1。我只期望在Storyboard中提供解决方案,因为我完全在Storyboard中进行UI设计。如果Storyboard的功能有限,无法满足我的需求,请告知如何通过整个应用程序的代码实现相同的功能?

就尺寸类别和设备类型而言,它们都是相同的。如果您正在正确执行自动布局,则视图大小将随着屏幕比例的变化而变化。您能展示一下为什么需要不同的字体大小的屏幕截图吗? - matt
@matt,您可以在此处查看iPhone 6 Plus的文件。由于NDA的限制,我无法分享真实版本。我只需要在每个标签之间留出间隙,并且我已经添加了一些控件。https://www.dropbox.com/s/ycar93s6j8djv33/Screen%20Shot%202014-11-22%20at%2012.51.44%20AM.png?dl=0 - Bluewings
谢谢提供截图,但您认为它有什么问题? - matt
@matt,要求所有屏幕大小都具有相同的布局。因此,如果屏幕大小增加,则标签大小和标签到文本字段间距将自动增加。 :( 目前,大小与较小的大小相同。 - Bluewings
1
要求是所有屏幕尺寸都有相同的布局。这是一个愚蠢的“要求”。整个理念在于_适应_不断变化的多种屏幕尺寸。这就是为什么关于此主题的WWDC视频是关于_适应_的。说“相同的布局”是与适应相反的,是_呆板_的。 :)如果您不想适应,那么只需为iPhone 4s包含启动图像,并在iPhone 6模型上放大自己。然后您将拥有_完全相同_ 的界面。 - matt
我知道这是一个愚蠢的要求,但我的设计师更愚蠢,他想要那样做 :( 顺便问一下,您能否详细说明一下iPhone 6型号的缩放问题?或者我可以为iPhone 6型号单独使用不同的故事板吗? - Bluewings
10个回答

24

另一种根据iPhone类型调整字体大小的选择是使用“用户定义的运行时属性(User Defined Runtime Attributes)”。

定义一个扩展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
        }
    }
}
为了确定当前的模型名称,请参考以下答案: https://dev59.com/g18e5IYBdhLWcg3wJnyl#26962452 在Storyboard中,选择您想要调整的标签,打开右侧面板,选择“Identity Inspector”,并将“adjustFontToRealIPhoneSize”属性添加到用户定义的运行时属性列表中(类型为“布尔”且复选框已选中)。
对于每个要调整的标签都执行相同的操作(复制和粘贴出奇地有效)。

5
您可以在该扩展中添加@IBInspectable,这样您就可以直接从“属性检查器”编辑它。 - Fábio Oliveira
有人可以提供它的Objective-C版本吗? - Bista
1
我认为,钉定精确的模型并不是面向多尺寸设备的(即使是有意)解决方案。 - Jonny
将字符串与模型名称进行比较并不是一个好主意(委婉地说)。你应该使用大小类别。检查各个维度的大小类别,以确定使用什么大小的字体。请参见我的答案示例。 - Michael Peterson

8

在故事板中使用紧凑宽度和常规高度

在故事板中使用紧凑宽度和常规高度

通过添加乘数来添加相对于父视图的高度和宽度的布局约束。比如说,如果你有一个大小为父视图一半的图像视图,则添加乘数0.5。

输入图像描述


你能否稍微解释一下乘法器,或者给我一些阅读材料的链接吗? - Bluewings
目前我已经按照你在图片中提到的设置了大小类,但是在iPhone 6 Plus上,我的字体看起来太小了。 - Bluewings
谢谢回答。我已经在评论中添加了一张截图,希望您能看到并理解我的需求。 - Bluewings
帮了我个大忙。谢谢! - NightFury
@Jignesh - 对我来说它部分地起作用。图像大小减小了,但如何管理每个图像之间的间距?如何减少间距?请告诉我。 - Lohith Korupolu
显示剩余2条评论

2

@iBhaviks答案的Swift版本:

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

请不要鼓励将其与特定型号进行比较。这段代码将在一年内崩溃。学会正确使用像苹果意图的大小类。 - Michael Peterson

2

我对于不同iPhone设备中字体大小的sizeClass没有太多的了解,但是我找到了这个解决方案。

  1. 将这个方法添加到你的工具类中。
  2. 只需要将你的父视图传递给这个方法,这个方法是递归的,所以如果你传递self.view,那么所有的子视图都会被设置。
  3. 根据你的需要更改字体大小。
-(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];
    }
}
}

我对在不同的iPhone设备上为不同字体大小使用sizeClass并没有太多的了解,这就是你应该停下来学习如何使用sizeClasses而不是投机取巧。这段代码如何处理iPhone 7、8、iPad Pro等设备? - Michael Peterson

2
请查看 UILabel类参考文档 中的 adjustsFontSizeToFitWidth 属性。该属性可根据不同设备进行优美的调整。
label.adjustsFontSizeToFitWidth = YES;

1

可能有点晚了,但我需要一个能够在任何设备上自适应的标签,并使用了这种方法。

创建一个UILabel的新子类,在.h文件中加入以下代码...

#import <UIKit/UIKit.h>

IB_DESIGNABLE

@interface OTHD_ScalableLabel : UILabel

@property (nonatomic, assign) IBInspectable CGFloat fontScale;

@end

在 .m 文件中放入以下内容...
#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

你可以在IB中更改类,使用IBInspectable,你就可以缩放标签。显然,对于挑剔的人来说,这不是一种好的通用方法,但有些情况下你可能需要一个大的标签,在iPhone和iPad上都可以全屏显示。

1
这是一个函数示例,我在运行时使用它来切换两种不同的字体大小。它根据水平尺寸类别决定使用哪种字体 - 这基本上将设备分为两组“iPad”和“iPhone”。这是一个很好的参考,可以了解哪些设备属于哪些尺寸类别:http://useyourloaf.com/blog/size-classes/
  • iPad及以上
  • iPhone Plus及以下
 func chooseFont(compactFont: UIFont, regularFont: UIFont) -> UIFont {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    return appDelegate.window!.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.compact ? compactFont : regularFont
}

1

在苦苦挣扎后,我终于找到了我需要的东西,所以现在将其发布给未来的读者。

  1. 目前还没有办法使用Size classes唯一地识别iPhone 6模型的竖屏。但是,您可以使用紧凑的宽度和常规的高度来设计所有iPhone竖屏幕
  2. 要更改字体大小,您必须使用代码确定应用程序当前运行的iPhone,并根据该信息设置字体大小
  3. 对于我的要求-所有屏幕尺寸都使用相同的布局-请在宽度和高度约束中使用乘数。查看Jignesh对此问题的答案以了解更多信息。

编辑 2015年9月24日 我最近发现了一种使用UITraitColleection仅针对iPhone 6 Plus自定义大小类的方法,因此您不需要编写太多代码。我希望这个link将帮助未来的某些人。


但是,如果我们还想为iPhone支持横向模式,使用 UITraitCollection 的方法就不会起作用。 - nickcheng

1
也许你可以为大屏幕设置完美的字体大小,然后将自动收缩设置为小屏幕的最小字体大小,这样你就可以拥有动态字体大小而无需编码。
无论如何,您都必须设置标签的约束以根据屏幕大小调整其大小。
希望这可以帮到你。

但是如果文本换行(超过一行),自动缩小就不起作用了。 - matt
如果是多行标签,那么可能需要一些代码来解决。如果不是,那么我认为这是一个不错的选择。 - Себастьян Толедо

0
根据您的屏幕截图,我建议使用动态类型。这样用户可以控制文本的大小。

那么你的意思是作为开发者,我不需要关心字体大小和控件之间的间隔。因此,在更大的屏幕上,我的应用程序将会有很多空白,并且肯定会影响用户体验。 - Bluewings
为什么应该有“很多空隙”呢?这是自动布局要处理的。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接