1:iPhone尺寸规格
2:屏幕尺寸
我们通常所说的iPhone5屏幕尺寸为4英寸、iPhone6屏幕尺寸为4.7英寸,指的是显示屏对角线的长度(diagonal)
3:像素密度PPI
PPI(Pixel Per Inch by diagonal):表示沿着对角线,每英寸所拥有的像素(Pixel)数目。
PPI数值越高,代表显示屏能够以越高的密度显示图像,即通常所说的分辨率越高、颗粒感越弱。
根据勾股定理
计算结果稍有出入,这是因为像素的离散采样有锯齿效应。
4:缩放因子(scale factorbetween logic point and device pixel)
(1)Scale起源
早期的iPhone3GS的屏幕分辨率是320*480(PPI=163),iOS绘制图形(CGPoint/CGSize/CGRect)均以point为单位(measured in points):
1 point = 1 pixel(Point Per Inch=Pixel Per Inch=PPI)
后来在iPhone4中,同样大小(3.5 inch)的屏幕采用了Retina显示技术,横、纵向方向像素密度都被放大到2倍,像素分辨率提高到(320x2)x(480x2)= 960x640(PPI=326), 显像分辨率提升至iPhone3GS的4倍(1个Point被渲染成1个2x2的像素矩阵)。
但是对于开发者来说,iOS绘制图形的API依然沿袭point(pt,注意区分印刷行业的“磅”)为单位。
在同样的逻辑坐标系下(320x480):
1 point = scale*pixel
(在iPhone4~6中,缩放因子scale=2;在iPhone6+中,缩放因子scale=3)。
结论:
scale=绝对长度比(point/pixel)=单位长度内的数量比(pixel/point)
(2)UIScreen.scale
UIScreen.h
@property(nonatomic,readonly)CGFloatscaleNS_AVAILABLE_IOS(4_0);
为了自动适应分辨率,系统会根据设备实际分辨率,自动给UIScreen.scale赋值,该属性对开发者只读。
(3)UIScreen.nativeScale(iOS8新增了nativeScale属性:nativeScale与scale没有太大区别)
@property(nonatomic,readonly)CGFloatnativeScaleNS_AVAILABLE_IOS(8_0);
(4)机型判别
在同样的逻辑分辨率下,可以通过scale参数识别是iPhone3GS还是iPhone4(s)。以下基于nativeScale参数,定义了探测机型是否为iPhone6+的宏
// not UIUserInterfaceIdiomPad
#defineIS_IPHONE(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
// detect iPhone6 Plus based on its native scale
#defineIS_IPHONE_6PLUS(IS_IPHONE && [[UIScreenmainScreen] nativeScale] == 3.0f)
--------------------------------------------------------------------------------那么,同样的分辨率和scale,如何区分机型iPhone4与4s、iPhone5与5s呢?通过[[UIDevice currentDevice] model]只能判别iPhone、iPad、iPod大类,要判断iPhone具体机型型号,则需要通过sysctlbyname("hw.machine")获取详细的设备参数信息予以甄别。
5:@2x @3x及高倍图适配
(1)@2x
iPhone3GS时代,我们为一个应用提供图标(或按钮提供贴图),只需要icon.png。针对现在的iPhone4~6 Retina显示屏,需要制作额外的@2x高分辨率版本。
例如在iPhone3GS中,scale=1,用的图标 50x50pixel(logicalimage.size=50x50point);在iPhone4~6中,scale=2,则需要100×100pixel(logical image.size=50x50point,乘以image.scale=dimensions in pixels),并且命名为icon@2x.png。
如果APP要同时兼容iPhone3GS~iPhone6,则需要提供icon.png/icon@2x.png两种分辨率的图片。
(2)@3x
Phone6+在实际渲染时,downsampling/1.15(1242x2208->1080x1920),准确的讲,应该是@2.46x。苹果为方便开发者用的是@3x的素材,然后再缩放到@2.46x上。
如果APP要同时兼容iPhone3GS~iPhone6+,则需要提供icon.png/icon@2x.png/icon@3x.png三种分辨率的图片。需要注意的是,iOS APP图标的尺寸和命名都需要遵守相关规范。
参考:一张图帮你看懂 iPhone 6 Plus 屏幕分辨率
(3)加载图片的方式
<1>
+imageNamed:
该方法使用系统缓存,适合表视图重复加载图像的情形。同时该API根据UIScreen的scale,自动查找包含对应高倍图后缀名(@2x)的文件,如果找到二倍图,则image.scale=2.0,对应逻辑size大小以point度量(pixel度量的一半);如果没找到设置默认image.scale=1.0,对应逻辑size大小同像素尺寸。因此,
使用该方法,无需特意指定高倍图后缀。在实际运行时,系统如果发现当前设备是Retina屏(scale=2),会自动寻找"*@2x.png"命名格式的图片,加载针对Retina屏的图片素材,否则会失真。
<2>
+imageWithContentsOfFile
+imageWithData:(scale:)
-initWithContentsOfFile:
-initWithData:(scale:)
这组方法创建的UIImage对象没有使用系统缓存,并且指定文件名必须包含明确的高倍图后缀。
如果文件名包含@2x后缀,则image.scale=2.0;否则默认image.scale=1.0,同样对于Retina屏将会失真。
<3>
目前,适配iPhone6+时,除了一些铺满全屏的大图(LogoIcon、LaunchImage)需提供三倍图,其他的小图仍可沿用原有的二倍图自适应拉伸。
6:Screen Bounds & Application Frame
(1) UIScreen.bounds
// Bounds of entire screen in points(本地坐标系,起点为[0,0])
@property(nonatomic,readonly)CGRectbounds;
//考虑 转屏 的影响,按照实际屏幕方向(UIDevice Orientation)的宽高
#defineSCREEN_WIDTH([UIScreenmainScreen].bounds.size.width)
#defineSCREEN_HEIGHT([UIScreenmainScreen].bounds.size.height)
#defineSTATUSBAR_HEIGHT([UIApplicationsharedApplication].statusBarFrame.size.height)
//不考虑转屏的影响,只取竖屏(UIDevice OrientationPortrait)的宽高
#defineSCREEN_WIDTH MIN([UIScreen mainScreen].bounds.size.width, [UIScreenmainScreen].bounds.size.height)
#defineSCREEN_HEIGHT MAX([UIScreen mainScreen].bounds.size.height [UIScreenmainScreen].bounds.size.width)
#defineSTATUSBAR_HEIGHT MIN([UIApplicationsharedApplication].statusBarFrame.size.width,
[UIApplicationsharedApplication].statusBarFrame.size.height)
7:机型尺寸适配(Screen Scale Adaption)
待续