V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tunnyios
V2EX  ›  iOS

iOS 屏幕适配~~整理了一些屏幕适配的东西

  •  1
     
  •   tunnyios · 2016-05-21 17:10:19 +08:00 · 8310 次点击
    这是一个创建于 2868 天前的主题,其中的信息可能已经有所发展或是发生改变。

    欢迎关注我的 Blog tunnycoder.com

    整理了一些 iOS 屏幕适配的东西

    自从 Apple 出了 4.7 寸和 5.5 寸的 iphone 后,在 iOS 开发中, 屏幕适配也成为了一项很重要的工作。(PS:之前一直吐槽安卓各种屏幕适配好蛋疼,后来发现出来混总是要还的。)还好苹果公司也在为这条适配之路更好走,不断的改进着~本文记录了一些屏幕适配过程中的一些问题。

    4s 、 5/5s 、 6/6s 、 6p/6sp 的参数以及适配的参考基准建议

    | 机型 | 屏幕宽高(point) | 渲染像素(pixel) | 物理像素(pixel) | 屏幕对角线长度(英寸) | 屏幕模式 | | -------- |:---------:|:---------:|:---------:|:---------:|:---------:| ------:| |iPhone 2G/3G/3GS|320 * 480| 320 * 480| 320 * 480| 3.5(163PPI)| 1x| |iPhone 4/4s| 320 * 480| 640 * 960| 640 * 960| 3.5 (326PPI)| 2x| |iPhone 5/5s| 320 * 568| 640 * 1136| 640 * 1136| 4 (326PPI)| 2x| |iPhone 6/6s| 375 * 667| 750 * 1334| 750 * 1334| 4.7 (326PPI)| 2x| |iPhone 6Plus/6sPlus| 414 * 736| 1242 * 2208| 1080 * 1920| 5.5 (401PPI)| 3x| 设计和开发时一般选用 iphone6 作为基准尺寸,原因如下:

    1. 从中间尺寸向上和向下适配的时候界面调整的幅度最小。如果直接以 414pt 作为基准,那么适配到 320pt 的时候可能就会出现视觉比例失调。
    2. iPhone 6 plus 有两种显示模式,标准模式分辨率为 1242x2208 ,放大模式分辨率为 1125x2001 (即 iPhone 6 的 1.5 倍)。很多情况下这两种尺寸可以用 1.5 倍直接等比适配。如果 UI 设计师可以做两套,一般情况下都是使用 375pt 作为基准设计一套(用来切 @2x 图),然后再等比放大 1.5 倍,生成 1125px 的设计稿(用来切 @3x 图)。
    3. 1242x2208 这个奇葩的分辨率,不便于记忆和计算栅格。

    以 iphone6 作为基准尺寸,适配原则:文字流式,控件弹性,图片等比缩放。

    App 设计的几个技巧

    • 非矢量素材,就可以做尺寸最大的,之后再进行缩小。比如需要兼容 3x 的屏幕,就直接做最高那种图片。
    • 假如是那种导航栏,工具栏之类的背景图,需要横跨整个屏幕。可以只切一小块,让程序拉伸,拉伸方式是保持两边的像素不动,只拉伸最中间的一列像素。需要拉伸的话,横方向就不要出现一些渐变色。
    • 按钮的点击区域,不应该少于 44 像素,就算按钮的图片看起来比较小,也应该使得点按钮周围的透明区也有反应。

    启动高分辨率方法

    以前的旧工程跑 iphone6 和 iphone6plus 时,默认是「兼容模式」即系统会简单的把内容等比放大,但效果粗糙。此时程序中获取到的设备尺寸还是和 iphone5s 一个尺寸 320pt 。

    启动高分辨率模式的方法:

    • 在项目中添加 Launch Screen File Lanuch Screen 是 xcode6 和 iOS8 新加的功能,它用一个 xib 或者 storyboard 作为启动画面。 iOS 在旧版系统中启动时,该属性会被自动忽略,不会造成异常。

    补充启动动画

    iOS 启动动画的方式有两种:启动图和布局文件。 Xcode 6 是 LaunchScreen.xib ,到 Xcode 7 变成了 LaunchScreen.storyboard ,无可厚非,两者本质都是一样的。

    使用布局文件实现启动动画也很简单:获取LaunchScreen.storyboard 里的 ViewController,在把View 提取出来加到UIWindow显示做动画即可。这种方式的好处就是,获取大小就是屏幕的大小,而且只要你把不同屏幕的布局搞定了,系统会帮你生成好加在的启动页,这样就免去了判断和从新设置大小的麻烦,这样才是真适配嘛~

    //设置启动动画并跳转
      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
      [self.window makeKeyAndVisible];
      UIViewController* myvc = [[UIViewController alloc] initWithNibName:nil bundle:nil];
      self.window.rootViewController = myvc;
    
      UIViewController *viewController = [[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateViewControllerWithIdentifier:@"LaunchScreen"];
      self.lunchView = viewController.view;
      [self.window addSubview:self.lunchView];
      self.imageV = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
      self.imageV.image = [UIImage imageNamed:@"default0"];
      self.timerIndex = 0;
      self.timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(updateImage:) userInfo:nil repeats:YES];
      [self.lunchView addSubview:self.imageV];
      [self.window bringSubviewToFront:self.lunchView];
    

    PS: 注意升级 Xcode 7 之后 ios 9 一启动程序就报错Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294

    原因是:新的 SDK 不允许在设置rootViewController之前做过于复杂的操作。解决办法: 先设置个rootVIewController之后重新赋值。

    Autolayout 与 size Classes 适配

    Autolayout 是在 xcode5 之后流行起来的,解决了 Autoresizing 在 storyboard 中,无法实现兄弟控件的布局的问题。 Autolayout 的核心是参照和约束。用相对位置解决问题。

    Autolayout 可以动态的修改约束,只需要将对应的约束拖到对应的 view 或者对应的 Controller 中,进行动态修改,并添加一句 [添加了约束的 view layoutIfNeeded]; 就会在下一个消息循环里调用里刷新屏幕的时候调用updateViewConstraints方法。 Autolayout 添加动画也是这样做的。

    // 1. 修改约束
      xxxxxxxx
    // 2.执行动画
        [UIView animateWithDuration:5 animations:^
    	{
            // 让 view 上的约束执行动画
            [self.view layoutIfNeeded];
        }];
    

    注: iOS 建议:忘掉 Frame ,使用 Autolayout, 使用比例来固定尺寸而非具体的尺寸大小;相同级别的控件他们的约束在父控件去找

    SizeClass 实现屏幕多样化,界面大统一。

    1. 仅仅是对屏幕进行了分类,排布 UI 元素还需要 autolayout
    2. 不再有横竖屏概念,只有屏幕尺寸的概念,无法单独区分出 5.5 寸竖屏
    3. 不再有具体尺寸的区别,只有抽象尺寸的概念
    4. 把宽度和高度分为三种情况:Compact(紧凑) Any(任意) Regular(正常)

    SizeClass 各模式下的适配情况:

    • 宽高任意( WAHA ):任意设备
    • 宽任意高正常(WAHR): 3.5 寸竖屏, 4 寸竖屏, 4.7 寸竖屏, 5.5 寸竖屏, iPad 竖屏、 iPad 横屏
    • 宽任意高紧凑(WAHC): 3.5 寸横屏 , 4 寸横屏, 4.7 寸横屏, 5.5 寸横屏
    • 宽正常高任意(WRHA): 5.5 寸横屏, iPad 竖屏、 iPad 横屏
    • 宽正常高正常(WRHR): iPad 竖屏、 iPad 横屏
    • 宽正常高紧凑(WRHC): 5.5 寸横屏
    • 宽紧凑高任意(WCHA): 3.5 寸竖屏、 3.5 寸横屏, 4 寸竖屏、 4 寸横屏, 4.7 寸竖屏、 4.7 寸横屏, 5.5 寸竖屏
    • 宽紧凑高正常(WCHR): 3.5 寸竖屏, 4 寸竖屏, 4.7 寸竖屏, 5.5 寸竖屏
    • 宽紧凑高紧凑(WCHC): 3.5 寸横屏, 4 寸横屏, 4.7 寸横屏

    SizeClass 的其他用途:

    通过 Image Asset 为不同的 SizeClass 配置不同的图片

    Label 的 FontSize 根据不同的 SizeClass 设置不同的字号

    SizeClass 关于代码中判断屏幕旋转问题

    • Apple 在 iOS 8 中引入了一个新的类,UITraitCollection。这个类封装了像水平和竖直方向的 Size Class 等信息。 iOS 8 的 UIKit 中大多数 UI 的基础类 (包括 UIScreenUIWindowUIViewControllerUIView) 都实现了 UITraitEnvironment 这个接口,通过其中的 traitCollection 这个属性,我们可以拿到对应的 UITraitCollection 对象,从而得知当前的 Size Class,并进一步确定界面的布局。

    注:如果项目要区分横竖屏幕、和支持 ipad 以及 ipad 横竖屏幕,应该一开始就提前沟通好,然后选择合适的 SizeClass 来进行操作,否则最后画好了之后再考虑横竖屏幕会很蛋疼(但也不是不能做)。

    Demo 就 Autolayout 和 SizeClass 写了一个 Demo,里面涉及了一些基本的使用,有兴趣的小伙伴可以下载看看

    Demo 下载

    2 条回复    2016-05-22 11:21:28 +08:00
    ins
        1
    ins  
       2016-05-22 07:59:22 +08:00
    这个好..很有用
    xiaoc19
        2
    xiaoc19  
       2016-05-22 11:21:28 +08:00
    Autolayout 有些约束想的头疼
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4524 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 10:07 · PVG 18:07 · LAX 03:07 · JFK 06:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.