赞
踩
点(Points):
是iOS开发中引入的抽象单位,称作点。开发过程中所有基于坐标系的绘制都是以 point 作为单位,在iPhone 2G,3G,3GS的年代,point 和屏幕上的像素是完全一一对应的,即 320 * 480 (points), 也是 320 * 480 (pixels)
渲染像素 (Rendered Pixels):
Rendered Pixels: 渲染像素, 以 point 为单位的绘制最终都会渲染成 pixels,这个过程被称为光栅化。基于 point 的坐标系乘以比例因子可以得到基于像素的坐标系,高比例因子会使更多的细节展示,目前的比例因子会是 1x,2x,3x
物理像素(Physical Pixels):
Physical Pixels: 物理像素,就是设备屏幕实际的像素
设备屏幕的物理长度(Physical Device):
Physical Device: 设备屏幕的物理长度,使用英寸作为单位。比如iPhone 4屏幕是3.5英寸,iPhone 5 是4英寸,iphone 6是4.7英寸,这里的数字是指手机屏幕对角线的物理长度。实际上会是Physical Pixels的像素值(而不是Rendered Pixels的像素值)会渲染到该屏幕上, 屏幕会有 PPI(pixels-per-inch) 的特性,PPI 的值告诉你每英寸会有多少像素渲染。
更多关于IOS设备分辨率可以看The Ultimate Guide To iPhone Resolutions
机型 | 屏幕宽高(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, 7 | 375 * 667 | 750 * 1334 | 750 * 1334 | 4.7 (326PPI) | 2x |
iPhone 6 Plus, 6s Plus, 7 Plus | 414 * 736 | 1242 * 2208 | 1080 * 1920 | 5.5 (401PPI) | 3x |
iphone设备尺寸
机型 | 屏幕宽高(point) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iPhone 2g | 480×320 | 3:2 | 163ppi | 3.5 | iPhone1,1 | 2008.01 |
iPhone 3g | 480×320 | 3:2 | 163ppi | 3.5 | iPhone1,2 | 2008.06 |
iPhone 3gs | 480×320 | 3:2 | 163ppi | 3.5 | iPhone2,1 | 2009.06 |
iPhone 4 | 960×640 | 3:2 | 163ppi | 3.5 | iPhone3,1、iPhone3,2、iPhone3,3 | 2010.06 |
iPhone 4s | 960×640 | 3:2 | 326ppi | 3.5 | iPhone4,1 | 2011.10 |
iPhone 5 | 1136×640 | 16:9 | 326ppi | 4.0 | iPhone5,1、iPhone5,2 | 2012.09 |
iPhone 5c | 1136×640 | 16:9 | 326ppi | 4.0 | iPhone5,3、iPhone5,4 | 2013.09 |
iPhone 5s | 1136×640 | 16:9 | 326ppi | 4.0 | iPhone6,1、iPhone6,2 | 2013.09 |
iPhone 6 | 1334×750 | 16:9 | 401ppi | 4.7 | iPhone7,2 | 2014.09 |
iPhone 6 plus | 1920×1080 | 16:9 | 401ppi | 5.5 | iPhone7,1 | 2014.09 |
iPhone 6s | 1334×750 | 16:9 | 401ppi | 4.7 | iPhone8,2 | 2015.09 |
iPhone 6s plus | 1920×1080 | 16:9 | 401ppi | 5.5 | iPhone8,1 | 2015.09 |
iPhone 5 SE | 1136×640 | 16:9 | 401ppi | 4.0 | iPhone8,4 | 2016.03 |
iPhone 7 | 1334×750 | 16:9 | 401ppi | 4.7 | iPhone9,1、iPhone9,3 | 2016.09 |
iPhone 7 plus | 1920×1080 | 16:9 | 401ppi | 5.5 | iPhone9,2、iPhone9,4 | 2016.09 |
iPhone 8 | 1334×750 | 16:9 | 401ppi | 4.7 | iPhone10,1、iPhone10,4 | 2017.09 |
iPhone 8 plus | 1920×1080 | 16:9 | 401ppi | 5.5 | iPhone10,2、iPhone10,5 | 2017.09 |
iPhone X | 2436×1125 | 18:9 | 458ppi | 5.8 | iPhone10,3、iPhone10,6 | 2017.09 |
iPhone XS | 2436×1125 | 18:9 | 458ppi | 5.8 | iPhone11,2 | 2018.09 |
iPhone XS Max | 2688×1242 | 18:9 | 458ppi | 6.5 | iPhone11,4、iPhone11,6 | 2018.09 |
iPhone XR | 1792×828 | 19.5:9 | 326ppi | 6.1 | iPhone11,8 | 2018.09 |
ipad 尺寸
机型 | 屏幕宽高(point) | 屏幕模式(Scale) | 物理像素(pixel) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iPad | 1024×768 | @1x | 1024×768 | 4:3 | 163ppi | 9.7 | iPad1,1 | 2010.01 |
iPad 2 | 1024×768 | @1x | 1024×768 | 4:3 | 163ppi | 9.7 | iPad2,1、iPad2,2、iPad2,3、iPad2,4 | 2011.03 |
iPad 3(New) | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad3,1、iPad3,2、iPad3,3 | 2012.03 |
iPad 4 | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad3,4、iPad3,5、iPad3,6 | 2012.10 |
iPad 5 | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad6,11、iPad6,12 | 2017.03 |
ipad Air尺寸
机型 | 屏幕宽高(point) | 屏幕模式(Scale) | 物理像素(pixel) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iPad Air | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad4,1、iPad4,2、iPad4,3 | 2013.10 |
iPad Air 2 | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad5,3、iPad5,4 | 2014.10 |
iPad Pro 尺寸
机型 | 屏幕宽高(point) | 屏幕模式(Scale) | 物理像素(pixel) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iPad Pro 12.9-inch | 1366×1024 | @2x | 2732×2048 | 4:3 | 264ppi | 12.9 | iPad6,7、iPad6,8 | 2015.09 |
iPad Pro 9.7-inch | 1024×768 | @2x | 2048×1536 | 4:3 | 264ppi | 9.7 | iPad6,3、iPad6,4 | 2016.03 |
iPad Pro 12.9-inch 2 | 1366×1024 | @2x | 2732×2048 | 4:3 | 264ppi | 12.9 | iPad7,1、iPad7,2 | 2017 |
iPad Pro 10.5 | 1112×834 | @2x | 2224×1668 | 4:3 | 264ppi | 10.5 | iPad7,3、iPad7,4 |
ipad Mini尺寸
机型 | 屏幕宽高(point) | 屏幕模式(Scale) | 物理像素(pixel) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iPad mini | 1024×768 | @1X | 1024×768 | 4:3 | 163 | 7.9 | iPad2,5、iPad2,6、iPad2,7 | 2012.10 |
iPad mini 2 | 1024×768 | @2X | 2048×1536 | 4:3 | 326 | 7.9 | iPad4,5、iPad4,6、iPad4,7 | 2013.10 |
iPad mini 3 | 1024×768 | @2X | 2048×1536 | 4:3 | 326 | 7.9 | iPad4,7、iPad4,8、iPad4,9 | 2014.10 |
iPad mini 4 | 1024×768 | @2X | 2048×1536 | 4:3 | 326 | 7.9 | iPad5,1、iPad5,2 | 2015.09 |
iPod Touch尺寸
机型 | 屏幕宽高(point) | 屏幕模式(Scale) | 物理像素(pixel) | 比例 | 像素密度(PPI) | 屏幕尺寸 | 型号代码 | 发布日 |
iTouch | 480*320 | @1X | 480*320 | 3:2 | 163ppi | 3.5 | iPod1,1 | 2007.09 |
iTouch 2 | 480*320 | @1X | 480*320 | 3:2 | 163ppi | 3.5 | iPod2,1 | 2008.09 |
iTouch 3 | 480*320 | @1X | 480*320 | 3:2 | 163ppi | 3.5 | iPod3,1 | 2009.09 |
iTouch 4 | 480*320 | @2X | 960*640 | 3:2 | 326ppi | 3.5 | iPod4,1 | 2010.09 |
iTouch 5 | 568*320 | @2X | 1136*640 | 16:9 | 326ppi | 4.0 | iPod5,1 | 2012.09 |
iTouch 6 | 568*320 | @2X | 1136*640 | 16:9 | 326ppi | 4.0 | iPod7,1 | 2015.07 |
1x, 2x, 3x 的含义:
屏幕模式,描述的就是屏幕中一个点有多少个 Rendered Pixels 渲染,对于2倍屏(又称 Retina 显示屏),会有 2 * 2 = 4 个像素的面积渲染,对于3倍屏(又称 Retina HD 显示屏),会有 3 * 3 = 9 个像素的面积渲染。
iOS 开发中,所有控件的坐标以及控件大小都是以点为单位的,假如我在屏幕上需要展示一张 20 * 20 (单位:point)大小的图片,那么设计师应该怎么给我图呢?这里就会用到屏幕模式的概念,如果屏幕是 2x,那么就需要提供 40 * 40 (单位: pixel)大小的图片,如果屏幕是 3x,那么就提供 60 * 60 大小的图片,且图片的命名需要遵守以下规范: Standard:<device_modifier>.<filename_extension> High resolution:@2x<device_modifier>.<filename_extension> High HD resolution:@3x<device_modifier>.<filename_extension>
ImageName: 图片名字,根据场景命名 device_modifier: 可选,可以是 ~ipad 或者 ~iphone, 当需要为 iPad 和 iPhone 分别指定一套图时需要加上此字段 filename_extension: 图片后缀名,iOS中使用 png 图片
例如: MyImage.png - 1x 显示屏自动加载的图片版本 MyImage@2x.png - 2x 显示屏自动加载的图片版本 MyImage@3x.png - 3x 显示屏自动加载的图片版本 MyImage@2x~iphone.png - 2x iPhone 和 iPod touch 显示屏自动加载的图片版本 MyImage@3x~iphone.png - 3x iPhone and iPod 显示屏自动加载的图片版本
2x屏幕的设备会自动加载 xxx@2x.png 命名的图片资源,3x屏幕的设备会自动加载 xxx@3x.png 的图片, 现在基本没有 1x屏幕的设备了,可以不用提供这个分辨率的图片了。
现在APP设计开发必须考虑适配大、中、小三种屏幕。所以如何做到交付一套设计稿解决适配大中小三屏的问题?设计和开发之间采用什么协作模式?
一个基本思路是:
选择一种尺寸作为设计和开发基准;
定义一套适配规则,自动适配剩下两种尺寸;
特殊适配效果给出设计效果。
更多详情可以参考这篇文章:手机淘宝的设计方案
参考手机淘宝的设计方案如下:
第一步,视觉设计阶段,设计师按宽度750px(iPhone 6)做设计稿,除图片外所有设计元素用矢量路径来做。设计定稿后在750px的设计稿上做标注,输出标注图。同时等比放大1.5倍生成宽度1125px的设计稿,在1125px的稿子里切图。
第二步,输出两个交付物给开发工程师:一个是程序用到的@3x切图资源,另一个是宽度750px的设计标注图。
第三步,开发工程师拿到750px标注图和@3x切图资源,完成iPhone 6(375pt)的界面开发。此阶段不能用固定宽度的方式开发界面,得用自动布局(auto layout),方便后续适配到其它尺寸。
第四步,适配调试阶段,基于iPhone 6的界面效果,分别向上向下调试iPhone 6 plus(414pt)和iPhone 5S及以下(320pt)的界面效果。由此完成大中小三屏适配。
为什么选择iPhone 6作为基准尺寸?
当面对大中小三种屏幕需要适配的时候,很容易想到先做好一种屏幕,再去适配剩下两种屏幕。第一个决定是到底以哪种屏幕作为设计和开发的基准尺寸。我们选择中间尺寸的iPhone 6(750px/375pt)作为基准,基于几个原因:
从中间尺寸向上和向下适配的时候界面调整的幅度最小。375pt下的设计效果适配到414pt和320pt偏差不会太大。假设以414pt为基准做出很优雅的设计,到320pt可能元素之间比例就不是那么回事了,比如图片和文字之间视觉比例可能失调。
iPhone 6 plus有两种显示模式,标准模式分辨率为1242x2208,放大模式分辨率为1125x2001(即iPhone 6的1.5倍)。可见官方系统里iPhone 6和iPhone 6 plus分辨率之间就存在1.5倍的倍率关系。很多情况下这两种尺寸可以用1.5倍直接等比适配。
1242x2208这个奇葩的数值是苹果官方都不愿意公开宣传的一个分辨率,不便于记忆和计算栅格。640x1136虽然是广泛应用的一个分辨率,但是大屏时代依然以小尺寸为设计基准显然不合时宜,设计师会停留在小屏的视角做设计. 所以,iPhone6的750x1334是最适合基准尺寸
适配规则
:文字流式,控件弹性,图片等比缩放。
控件弹性指的是,navigation、cell、bar等适配过程中垂直方向上高度不变;水平方向宽度变化时,通过调整元素间距或元素右对齐的方式实现自适应。这样屏幕越大,在垂直方向上可以显示更多内容,发挥大屏幕的优势。
在使用masonary自动布局时,可以根据6s的屏幕设计,设置一个比例系数,比如
//以6/6s为准宽度缩小系数
#define kJLXWidthScale [UIScreen mainScreen].bounds.size.height/375.0
复制代码
//高度缩小系数
#define kJLXHeightScale [UIScreen mainScreen].bounds.size.height/667.0
复制代码
这样在布局的的时候,可以考虑使用上这个系数设置高度
UIButton *createrButton = [[UIButton alloc] init];
[self.view addSubview:createrButton];
UIEdgeInsets padding = UIEdgeInsetsMake(0, 10, 65, 10);
[createrButton setBackgroundImage:[UIImage imageNamed:@"common_button_pink"] forState:UIControlStateNormal];
[createrButton mas_makeConstraints:^(MASConstraintMaker *make){
make.left.equalTo(self.view.mas_left).with.offset(padding.left);
make.height.equalTo(@(60*kJLXHeightScale));
make.bottom.equalTo(self.view.mas_bottom).with.offset(-padding.bottom);
make.right.equalTo(self.view.mas_right).with.offset(-padding.right);
}];
复制代码
这样在5s小屏手机上面,按钮的高度就会根据比例系数来动态调整大小。
之前Jimu 1.0中用到的布局转换主要通过下面这个函数来转换实际的宽度或高度:
横屏下,水平方向适配函数
/// 设备横屏下,水平方向适配·
///
/// - Parameters:
/// - iPhone6Scale: iPhone6 水平方向@2x尺寸
/// - iPadScale: 分辨率比例为768*1024的iPad 水平方向@2x尺寸
/// - Returns: 适配后的尺寸
func layoutHorizontal(iPhone6 iPhone6Scale: Float, iPad iPadScale: Float) -> Float {
let iphoneWidth = iPhone6Scale / 2
let iPadWidth = iPadScale / 2
var newWidth: Float = 0
switch Device.type() {
case .iPhone4:
newWidth = iphoneWidth * (480.0 / 667.0)
case .iPhone5:
newWidth = iphoneWidth * (568.0 / 667.0)
case .iPhone6:
newWidth = iphoneWidth
case .iPhone6p:
newWidth = iphoneWidth * (736.0 / 667.0)
case .iPhoneX:
newWidth = iphoneWidth * ((812.0 - 78) / 667.0)
case .iPhoneXR:
newWidth = iphoneWidth * ((896.0 - 78) / 667.0)
case .iPad_768_1024:
newWidth = iPadWidth
case .iPad_834_1112:
newWidth = iPadWidth * (1112.0 / 1024.0)
case .iPad_1024_1366:
newWidth = iPadWidth * (1366.0 / 1024.0)
}
return newWidth
}
复制代码
设备横屏下,垂直方向适配函数
/// 设备横屏下,垂直方向适配
///
/// - Parameters:
/// - iPhone6Scale: iPhone6 垂直方向@2x尺寸
/// - iPadScale: 分辨率比例为768*1024的iPad 垂直方向@2x尺寸
/// - Returns: 适配后的尺寸
func layoutVertical(iPhone6 iPhone6Scale: Float, iPad iPadScale: Float) -> Float {
let iphoneHeight = iPhone6Scale / 2
let iPadHeight = iPadScale / 2
var newHeight: Float = 0
switch Device.type() {
case .iPhone4:
newHeight = iphoneHeight * (320.0 / 375.0)
case .iPhone5:
newHeight = iphoneHeight * (320.0 / 375.0)
case .iPhone6:
newHeight = iphoneHeight
case .iPhone6p:
newHeight = iphoneHeight * (414.0 / 375.0)
case .iPhoneX:
newHeight = iphoneHeight * (375.0 / 375.0)
case .iPhoneXR:
newHeight = iphoneHeight * (414.0 / 375.0)
case .iPad_768_1024:
newHeight = iPadHeight
case .iPad_834_1112:
newHeight = iPadHeight * (834.0 / 768.0)
case .iPad_1024_1366:
newHeight = iPadHeight * (1024.0 / 768.0)
}
return newHeight
}
复制代码
这种适配方式,可以满足横屏下适配各种设备,但是所有布局的代码都需要调用这两个函数,浸入性很强。所以需要优化一下。
先来看一下之前Jimu 1.0 是通过一个自定义枚举来实现的,这样的不好的地方也是浸入性很强,每个调用的地方都需要用这个枚举值。
/// 获取设备型号
enumDevice{
caseiPhone4 /// 4/4s 320*480 @2x
caseiPhone5 /// 5/5C/5S/SE 320*568 @2x
caseiPhone6 /// 6/6S/7/8 375*667 @2x
caseiPhone6p /// 6P/6SP/7P/8P 414*736 @3x
caseiPhoneX /// X 375*812 @3x
// case iPhoneXS /// XS 375*812 @3x (同X)
caseiPhoneXR /// XR 414*896 @2x (放大模式下为 375*812)
// case iPhoneXSMAX /// XSMAX 414*896 @3x (同XR)
caseiPad_768_1024 /// iPad(5th generation)/iPad Air/iPad Air2/iPad pro(9.7) 768*1024 @2x
caseiPad_834_1112 /// iPad pro(10.5) 834*1112 @2x
caseiPad_1024_1366 /// iPad pro(12.9) 1024*1366 @2x
/// 判断具体设备
///
/// - Returns: 具体设备名
staticfunctype()->Device{
switchscreenWidth{
case480.0:
return.iPhone4
case568.0:
return.iPhone5
case667.0:
return.iPhone6
case736.0:
return.iPhone6p
case812.0:
return.iPhoneX
case896.0:
return.iPhoneXR
case1024.0:
return.iPad_768_1024
case1112.0:
return.iPad_834_1112
case1366.0:
return.iPad_1024_1366
default:
return.iPad_768_1024
}
}
/// 判断是否为iPad
///
/// - Returns: true 是, false 否
staticfuncisIPad()->Bool {
// print("() = \(self.type())")
return(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiom.pad)
}
staticfuncisIPhone5()->Bool{
returnDevice.type()==Device.iPhone5?true:false
}
staticvarsafeAreaInsets:UIEdgeInsets{
if#available(iOS11.0,*){
returnUIApplication.shared.delegate?.window??.safeAreaInsets??.zero
}
return.zero
}
staticvarsafeScreenWidth:CGFloat{
returnUIScreen.main.bounds.width-safeAreaInsets.left-safeAreaInsets.right
}
staticvarsafeScreenHeight:CGFloat{
returnUIScreen.main.bounds.height-safeAreaInsets.top-safeAreaInsets.bottom
}
}
复制代码
将上面设备类型判断代码优化为UIDevice的一个类扩展
extensionUIDevice {
funcVersion()->String{
letappVersion: String=Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as!String
returnappVersion
}
@objcpublicclassfuncisiPhoneX() ->Bool {
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width: 1125, height: 2436)))! {
returntrue
}
returnfalse
}
publicclassfuncisiPhone6PlusBigMode() ->Bool {
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width: 1125, height: 2001)))! {
returntrue
}
returnfalse
}
publicclassfuncisiPhone6Plus() ->Bool {
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width:1242, height: 2208)))! {
returntrue
}
returnfalse
}
publicclassfuncisiPhone6BigMode() ->Bool{
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width: 320, height: 568)))! {
returntrue
}
returnfalse
}
publicclassfuncisiPhone6() ->Bool {
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width:750, height: 1334)))! {
returntrue
}
returnfalse
}
publicclassfuncisiPhone5() ->Bool {
if (UIScreen.main.currentMode?.size.equalTo(CGSize.init(width: 640, height: 1136)))! {
returntrue
}
returnfalse
}
publicclassfuncisiOS11() ->Bool {
if#available(iOS11.0, *) {
returntrue
} else {
returnfalse
}
}
publicclassfuncisiOS10() ->Bool {
if#available(iOS10.0, *) {
returntrue
} else {
returnfalse
}
}
publicclassfuncisiOS9() ->Bool {
if#available(iOS9.0, *) {
returntrue
} else {
returnfalse
}
}
publicclassfuncisiOS8() ->Bool {
if#available(iOS8.0, *) {
returntrue
} else {
returnfalse
}
}
publicclassfuncisAiPad() ->Bool {
ifUIDevice.current.userInterfaceIdiom==UIUserInterfaceIdiom.pad {
returntrue
}
returnfalse
}
}
复制代码
然后为了简化调用,可以定义一个全局变量
// MARK: - 判断 机型
let isiPhone5 = UIDevice.isiPhone5()
let isiPhone6 = UIDevice.isiPhone6()
let isiPhone6BigModel = UIDevice.isiPhone6BigMode()
let isiPhone6Plus = UIDevice.isiPhone6Plus()
let isiPhone6PlusBigMode = UIDevice.isiPhone6PlusBigMode()
let isiPhoneX = UIDevice.isiPhoneX()
let isIpad = UIDevice.isAiPad()
// MARK: - 系统类型
let kisiOS11 = UIDevice.isiOS11()
let kisiOS10 = UIDevice.isiOS10()
let kisiOS9 = UIDevice.isiOS9()
let kisiOS8 = UIDevice.isiOS8()
复制代码
定义全局变量简化屏幕宽度,高度计算
letscreenWidth=max(UIScreen.main.bounds.height,UIScreen.main.bounds.width)
letscreenHeight=min(UIScreen.main.bounds.height,UIScreen.main.bounds.width)
letscreenBounds=UIScreen.main.bounds
复制代码
extensionNSInteger{
/// iphone 5 上的大小
///
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。