UIScreen对象包含了整个屏幕的边界矩形。当构造应用的用户界面接口时,你应该使用该对象的属性来获得推荐的矩形大小,用以构造你的程序窗口。

CGRect bound = [[UIScreen mainScreen] bounds];  // 返回的是带有状态栏的Rect  
CGRect frame = [[UIScreen mainScreen] applicationFrame];  // 返回的是不带有状态栏的Rect  
float scale = [[UIScreenmainScreen] scale]; // 得到设备的自然分辨率  
 

let mainScreen = UIScreen.mainScreen();

window = UIWindow(frame: UIScreen.mainScreen().bounds);

println("bounds: \(mainScreen.bounds)\napplicationFrame:\(mainScreen.applicationFrame)\nscale:\(mainScreen.scale)");

println(window!.screen === UIScreen.mainScreen());

window!.makeKeyAndVisible() ;

//[email protected]

let image = UIImage(named:"test");

let imageView = UIImageView(image: image);

println(image.scale);//2.0

println(image.size);//160 120

println(imageView.bounds.width);//160.0

window!.addSubview(imageView);

输出的结果:

bounds: (0.0,0.0,768.0,1024.0)

applicationFrame:(0.0,20.0,768.0,1004.0)

scale:2.0

true

对于scale属性需要做进一步的说明:
    以前的iphone 设备屏幕分辨率都是320*480,后来apple 在iPhone 4中采用了名为Retina的显示技术,iPhone 4采用了960x640像素分辨率的显示屏幕。由于屏幕大小没有变,还是3.5英寸,分辨率的提升将iPhone 4的显示分辨率提升至iPhone 3GS的四倍,每英寸的面积里有326个像素。
scale属性的值有两个:
scale = 1; 代表普通屏,分辨率为bounds.width x  bounds.height
scale = 2; 代表retina屏 bounds.width*2  x bounds.height*2
使用UIScreen获取的bounds和frame,程序会自动给UIScreen.scale赋值,[UIScreen mainScreen].scale = 1.0 or 2.0。
 
对dpi和ppi的理解:
DPI是每英寸的点数,可以简单理解为点的密度。
PPI是每英寸的像素数,可以简单理解为像素密度。
点和像素有区别吗?很多时候,一个点 = 一个像素。但是,并不尽然,如iPhone的视网膜屏幕,它一个点包含了四个像素,大大提高了显示清晰度。

我们使用的显示器,一般都是一个点一个像素..iphone4是1个点两个像素.当在scale=2.0的屏幕上使用@2x的图片,实际上就是告诉ios,这个图片再显示屏幕上一个点需要显示两个像素,他image的width和height就是缩小了两倍 ,该宽度和告诉.也是点数..

所以只要制作的时候做一份640*960的尺寸的ui作为@2x就可以了.

支持高分辨率显示屏的清单

为了适应具有高分辨率显示屏的设备,需要做如下几项:

  • 在应用程序包中,为每个图片资源提供高分辨的图片
  • 为应用和文档图标提供高分辨率的图片
  • 基于矢量的图形和内容,要如以前一样继续使用Core Graphics和UIKit的drawing代码
  • 直接使用Core Animation图层时,在绘画之前可能需要调整比例系数(scale factor)
  • 使用OpenGL ES进行绘画,要判断是否需要加入高分辨率绘画支持,要合理的设置图层的比例系数
  • 对于创建的自定义图片,需要更新创建图片的代码,要考虑比例系数的影响
  • 如果应用中直接提供了Core Animation图层的内容,要按需要调整代码

无偿得到的绘画优化

IOS中的绘画技术提供了强大的支持,帮助开发者以最佳的方式渲染绘画内容,而不管当前显示屏所处的是何种分辨率。

  • 标准的UIKit views(text views , buttons , table views , 等等)在任何分辨率下会保证正确的渲染
  • 基于矢量的内容(UIBezierPath , CGPathRef,PDF)自动充分利用任何额外的像素点来修复图形线条的锯齿。
  • 文本(Text)在高分辨率下自动补齐锯齿。
  • UIKit支持自动加载为高分辨率准备的图片(@2x)

现存的绘画代码之所以能以正常的方式工作,是因为本地的绘画技术,如Core Graphics已近考虑了当前的比例系数。例如,如果view实现的drawRect:方法,UIKit自动将当前屏幕的比例系数值设置到view中。此外,在绘画过程中,UIKit自动修正任何绘画环境使用的当前旋转矩阵(current tansformation matrix CTM),考虑view的比例系数。之后利用 drawRect方法生成的内容会在当前设备屏幕下以合适的比例进行缩放。

如果应用程序只使用本地的绘画技术来渲染其内容,唯一要做的是为使用的图片提供高分辨率的版本。只使用系统的view或只依赖矢量内容的应用可以不用做任何修改。但是使用了图片的应用程序在高分辨率显示屏下,需要提供这些图片的新版本。尤其注意的是,要将图片放大两倍,在水平和竖直方向上提供两倍于原来数量的像素,总的来说是要提供四倍的像素。

更新图片资源文件

运行在IOS4的应用程序现在要为每张图片提供两个单独的文件。一个用于标准分辨率下,另一个用于高分辨率。每组图片的命名约定如下:

  • 标准版: <ImageName><device_modifier>.<filename_extension>
  • 高分辨率版: <ImageName>@2x<device_modifier>.<filename_extension>

<ImageName>和<filename_extension>部分指定了文件的普通名称和扩展名。<device_modifier>部分是可选的,可以在字符串-ipad和-iphone二者中选一。这两个标识符可以为iPad和iPhone同一个文件的不同版本。新增的@2x标识符表明图片应用于高分辨率,系统知道该图片是标准图片在高分辨率下的变体。 
需要注意,创建高分辨率版本的图片需要与原始版本的图片放在application包下的同一位置。

加载图片到应用程序中

UIImage类处理了所有需要加载高分辨率图片到应用中的工作。当创建一个新的image对象后,只要以同样的名称来同时请求图片的标准版和高分辨率版即可。例如,如果有两张图片文件,名为Button.png和[email protected],只要用以下代码请求图片即可:

1UIImage* anImage = [UIImage imageNamed:@"Button"];

注意,在IOS4及以后的版本,可以省略文件扩展名而只提供图片名称即可。

在高分辨率显示屏下, imageNamed:, imageWithContentsOfFile:, 和initWithContentsOfFile: 方法自动查找具有@2x名称的图片。如果找到,则会加载该图片。如果没有提供给定图片的高分辨率版本,image对象仍会加载标准版的图片资源,并在绘画过程中将其缩放.

注意,如果使用Core Graphics创建图片,谨记Quartz图片并没有一个显示的比例系数,它们的比例系数会假定为1.0.如果从 CGImageRef数据类型中创建UIImage对象,需要使用 initWithCGImage:scale:orientation:方法来执行该创建操作。该方法允许添加一个指定的比例系数到Quartz图像数据中。

UIImage对象在绘画过程中会自动考虑自身的比例系数。这样,只要在程序中提供正确的图片资源,任何渲染image的代码都会正常工作。

使用Image View展示图片

程序中使用UIImageView对象来展示图片,所有添加到该view的图片必须使用相同的比例系数。可以使用一个image view来展示单张图片,或者以动画的方式展示多张图片,并且也可以提供一张加亮图片(highlight image)。因此,如果为这些图片中的一张提供了高分辨率版本,那么其它的图片也必须提供相应的高分辨率图片。

更新应用程序图标(Application Icons)和加载图片(Lauch Images)

除了要更新应用程序中的自定义图片资源,同时也要为应用程序的图标和加载图片提供新的高分辨率版本。更新这些图片资源的过程与更新其它图片资源的处理过程是一样的。新建新版本的图片资源添加@2x标识符到图片文件名中,就像处理其它图片一样。例如,对于应用程序图标,要添加高分辨率的图片名到Info.plist文件 CFBundleIconFiles key中。

更新自定义的绘画代码

在应用程序中添加任何的自定义绘画代码,多数情况下是不用考虑当前设备的分辨率。本地的绘画技术会自动保证你在逻辑坐标空间下的坐标系正确映射到当前设备的像素点上。然而有时,也需要了解当前的比例系数以便正确渲染内容。在这些情况下,UIKit,Core Animation以及其它的系统框架会帮助进行正确的绘画。

以编程方式创建高分辨率位图图片

使用 UIGraphicsBeginImageContext函数创建位图时,需要调整代码以考虑比例系数。 UIGraphicsBeginImageContext函数一直以1.0的比例系数创建图片。如果当前设备的显示屏是高分辨率的,通过该方法创建的图片在渲染时可能会显得模糊。要创建比例系数为其它值的图片,需要使用UIGraphicsBeginImageContextWithOptions。该函数的处理与UIGraphicsBeginImageContext函数的处理过程一样。

  1. 调用UIGraphicsBeginImageContextWithOptions创建位图绘画环境(要添加合适的比例系数),将其push到图形栈中
  2. 使用UIKit或Core Graphics常用函数来添加图片内容
  3. 调用UIGraphicsGetImageFromCurrentImageContext 函数来获取位图内容
  4. 调用UIGraphicsEndImageContext 函数 将当前绘画环境pop出绘画栈

例如,以下代码创建一张200*200像素的位图。(像素点的数量由图片大小乘以比例系数决定)

1UIGraphicsBeginImageContextWithOptions(CGSizeMake(100.0,100.0), NO, 2.0);

注意,如果位图想要在当前设备下的main screen中以合适的比例系数缩放,在调用 UIGraphicsBeginImageContextWithOptions函数只要将scale参数设置为0.0即可。

调整本地内容适配高分辨率显示屏

如果想要在高分辨率下绘画不同的内容,需要使用当前的比例系数来修正绘画代码。例如,假设有一个view画1像素的边框线。在比例系数为2.0的设备上,使用 UIBezierPath对象以1.0的宽度画该线条,将会生成2像素宽的线条。在这种情况下,当前线条需要除以当前的比例系数来得到1像素的宽度。 
当然,基于比例系数改变绘画参数可能导致未知结果。1像素宽的线条在某些设备上看起来是正常的,但是在高分辨率的设备上看上去会比较细以至于看起来不清晰。这需要根据具体情况决定是否要做变动。

Core Animation Layers中的比例系数的解释

直接使用Core Animation layers提供内容的应用程序,需要调整代码并考虑比例系数的影响。通常情况下,在利用view的 drawRect:方法,或使用layer代理的 drawLayer:inContext:方法时,系统会自动考虑比例系数的影响并调整绘画环境。但是在view执行以下几种操作时,还是有必要去了解或如何改变比例系数:

  • 创建额外的Core Animation layers,设置不同的比例系数并组合到view的内容中去
  • 直接设置Core Animation layer的"contents"

Core Animation的集成引擎会查看每个layer的 contentsScale属性,决定layer的contents在集成的时候是否需要缩放。如果创建没有关联至view的layers,每个新的layer对象的比例系数初始化为1.0。如果不改变初始的比例系数,接下来直接将这样的layer画到高分辨率的显示屏上去时,layer的contents会自动缩放来弥补因不同的比例系数所造成的差异。如果不想layer的 contents被缩放,可以设置layer的比例系数为2.0,但是设置完成后的内容如果没有添加至高分辨率的显示屏,那么现存的内容可能会显得比预期的要小。修复该问题,则需要在高分辨率下使用该layer即可。

当直接设置layer的contents时,调整layer的content来适应不同的比例系数显得尤为重要。Quartz的图片直接在像素级别下工作,并不理会比例系数的设置。因此在创建CGImageRef对象来设置layer的contents之前,需要检测当前的比例系数并合理的调整image的大小。更要指出的是,当加载application bundle中的图片或使用 UIGraphicsBeginImageContextWithOptions函数创建图片时,都要调整图片的比例系数来与layer的比例系数保持一致。没有创建高分辨率的位图,其缩放比例的设置会按照之前说明的那样进行设置。

05-12 05:03