九十五、iphone屏幕旋转、改变 视图尺寸 和 布局控制

如果  你  曾经  用  用户界面套件  开发过  桌面窗口应用程序(比如:Windows,Mac OS X,Linux,Qt  或者  GTK+),你  就应该了解到  在窗口的尺寸改变时  我们设计的用户界面  也要能  正确地  改变  自己的尺寸。在这个过程中  我们  要确定  窗口中  哪些肉眼可见的部件  要移动位置,哪些  要根据窗口的变化  改变  自己的尺寸。

有  一件事情  很明显:在iphone  和  ipad这种运行iOS的设备上  窗口  并不能  像桌面应用程序一样  允许  用户  改变。然而  这样的设备  可以感知  物理上的转动,从而  允许  应用程序  以竖屏模式  或者  横屏模式  运行。既然  iOS设备  有  这样的能力,那么  我们  很有  必要  使  我们的应用程序用户界面布局  根据  设备的旋转  而  改变。

接下来  我们  要了解  设备转动  和  用户界面重新布局的机制。

创建  项目

首先  启动  Xcode。然后  创建  一个单一视图应用程序(Single View Application)。最后  将  产品名称  和  物件类型名称前缀  修改为  layout。

接着  点选  layoutViewController.xib这个文件,将  一个按钮  拖、放  到视图上。

启用  和  禁用  旋转特性

Xcode  提供的应用程序模板  默认  支持  旋转特性。然而  并不是  所有的应用程序  都适合  支持  旋转特性。如果  同时  支持  横屏模式  和  竖屏模式  在用户体验上  不能获得  任何提升,那么  我们  就应该禁用  旋转特性。如果  要禁用  旋转特性,我们  需要  在模板代码中  做出  小小的修改。

配备网膜屏幕的iphone型号  在竖屏模式下的尺寸  是  960像素高、640像素宽,在横屏模式下的尺寸  是  640像素高、960像素宽。老式的iphone型号  在竖屏模式下的尺寸  是  480像素高、320像素宽,在横屏模式下的尺寸  是  320像素高、480像素宽。如果  你的应用程序  要显示  标准状态栏,那么  实际可用的屏幕尺寸  就会减少。

当设备  监测到  自己  被旋转  到新的方向时,就会对  当前的视图控制器  采取  shouldAutorotateToInterfaceOrientation这项措施。为了改变  应用程序  对旋转特性的支持,我们  需要  重新  编写  shouldAutorotateToInterfaceOrientation这项措施的内容。

幸运的  是  在layoutViewController.m这个文件中,Xcode  已经  为我们  创建了  shouldAutorotateToInterfaceOrientation这项措施的模板:

这项措施  仅仅  附带  一个参数  那就是  UIInterfaceOrientation类型interfaceOrientation。参数interfaceOrientation的值  可以  是  以下的四个常量:

  • UIInterfaceOrientationPortrait
  • UIInterfaceOrientationPortraitUpsideDown
  • UIInterfaceOrientationLandscapeRight
  • UIInterfaceOrientationLandscapeLeft

这四个常量  分别  代表

  • 竖屏
  • 竖屏上下颠倒
  • 横屏底部朝右
  • 横屏底部朝左

shouldAutorotateToInterfaceOrientation:这项措施中的

就相当于

其中的变量interfaceOrientation  代表  当前设备的方向。这里的if()语句  先判断  当前的设备方向  是否是  竖屏上下颠倒。如果  当前的设备方向  不是  竖屏上下颠倒,那么  就  将  常量  YES  传递回去;如果  当前的设备方向  是  竖屏上下颠倒,则  将  常量  NO  传递回去。

如果  shouldAutorotateToInterfaceOrientation这项措施  产生  YES这个结果,那么  当前的视图  就会旋转  到  跟设备方向一致的方向;如果  这项措施  产生  NO这个结果,那么  当前视图的方向  就会  纹丝不动。

为了  使  我们的视图  能够  支持  任何方向的旋转,我们  只需要  将  shouldAutorotateToInterfaceOrientation:这项措施  改写成  这样:

这样的话  无论  变量interfaceOrientation的值  是多少,这项措施产生的结果  都是  常量YES。这  就意味着  设备的当前方向  无论  朝  哪个方向,视图  都会转向  当前设备的方向。接着  编译  并且  运行  程序。

测试  视图  能否正确旋转

如果  你  在真机上  测试  这个程序,你  只要将  你的iphone或者ipod touch  旋转到  某个方向,这个程序的视图  就会旋转  到相应的方向。如果  你  在iOS模拟器上  测试 这个程序,你  只需要  在按住  Command键的同时,按  方向键左键  或者  右键,就可以将  iOS模拟器  向左旋转  或者  向右旋转。

设置  自动改变尺寸

为了  使  对旋转的控制  更加容易,所有  UIView类型的物件,也就是  肉眼可见的物件,都有  一个特性  叫做  “自动改变尺寸”。自动改变尺寸这项特性  允许  我们  定义  在主视图尺寸  改变的情况下,主视图上的子视图  如何改变  尺寸  和  位置。

我们  先点选  layoutViewController.xib这个文件,将  其  载入  界面创建器。再在视图上  添加  一个按钮,就像  这样:

接着  我们  编译  并且  运行  这个程序,我们  可以看到  这样的结果:

然后  将  iOS模拟器  旋转  90度,我们  可以看到  这样的结果:

这  就是  典型的启用了旋转支持  而  用户界面  却没有  重新布局的例子。旋转  设备后,只有  上方的按钮  可见,而  这个按钮的位置  却没有改变,本来  这个按钮  应该 保持  在中间的位置的。下方的按钮  也没有改变  位置,因此  被移出到了  屏幕可见区域以外。

为了  保证  用户界面的正确布局,我们  需要对  两个按钮的“自动改变尺寸”设定  进行修改。我们  先点击  上方的按钮,然后  点击  Xcode窗口右方面板中的尺寸查看器:

在这个窗口中  最让人感兴趣的部分  就是  Autosizing这个标签上方的白色方框。外层的矩形  代表  主视图,里层的矩形  代表  子视图。子视图改变尺寸  和  位置的任何设置  都是  相对主视图而言的。在代表子视图的矩形里,有  两条互相交叉且两端带有箭头的线段。垂直的线段  和  水平的线段  分别  代表  你所选取的视图的宽度  和  长度。如果  这两条线段  是  虚线段,就表明  你所选取的子视图的尺寸  不会  随着主视图尺寸的改变  而  改变;如果  这两条线段  是  实线段,则表明  你所选取的子视图的尺寸  会  随着主视图尺寸的改变  而  改变。Example这个标签上方的图像  则展示了  当前设置的效果。其中  红色的方框  代表  子视图,而  白色的方框  代表  主视图。

通过设置  一个视图物件所包含的UIViewAutoResizingFlexibleHeight  和  UIViewAutoResizingFlexibleWidth这两个变量的值  也可以决定  这个视图的尺寸  是否  跟着其主视图尺寸的改变  而  改变。

在Autosizing这个标签上方的区域中  外层矩形的各条边  与  里层矩形的各条边之间的线段  代表  主视图各条边  与  子视图各条边之间的距离。如果  这些线段  是  实线段,那么  主视图  改变  尺寸时,子视图各条边  与  主视图各条边之间的距离  不变;如果  这些线段  是  虚线段,那么  主视图  改变  尺寸时,子视图各条边  与  主视图各条边之间的距离  就会  按照比例  改变。

要决定  子视图各条边  与  主视图各条变之间的距离  是否  随着主视图尺寸的改变  而  改变,还可以  通过设置  下面四个变量的值  来办到:

  • UIViewAutoResizingFlexibleLeftMargin(左侧)
  • UIViewAutoResizingFlexibleRightMargin(右侧)
  • UIViewAutoResizingFlexibleTopMargin(顶部)
  • UIViewAutoResizingFlexibleBottomMargin(底部)

在这里这个例子当中  我们  需要  两个按钮  相对于主视图的宽度来说  始终  保持  在正中央。于是  在Autosizing这个标签上方的区域中  我们  需要  点击  外层方框各条边  和  里层方框各条之间的实心线段,使  其  变成  虚线段,就像  这样:

最后  我们  需要  使  两个按钮的宽度  随着主视图宽度的变化  按比例  改变。于是  按住  shift键  选取  两个按钮,再在Autosizing这个标签上方的区域中  我们  点击  里层方框内的水平线段,使  其  变成  实线段,而  垂直线段  使  其  保持  虚线段  不变,就像  这样:

接着  我们  编译  并且  运行  这个程序。我们  将  iOS模拟器  向左  或者  向右  旋转  90度后,可以看到  这样的结果:

编写  代码  改变  尺寸  和  布局

虽然  在不少的情况之下  “自动改变尺寸”这项特性  都能  很好的  满足  你的要求,但是  这项特性  也有  一些限制。比如  在某些情况之下,你  可能需要  根据设备  是  横屏  或者  竖屏  从而  整体  改变  用户界面的布局。在这样的情况下  你  不但需要改变  视图元素的尺寸,还需要将  其  移动  到特定的位置。很明显  “自动改变尺寸”这个特性  就办不到  这点。有  一项解决办法  就是  在设备  旋转的时候  打断  视图的旋转,在视图  重新  绘制之前  改变  用户界面元素的尺寸  和  位置。在这里这个例子中  我们  需要编写  willAnimateRotationToInterfaceOrientation这项措施  并且  使  其  适用于  layoutViewController这类物件。willAnimateRotationToInterfaceOrientation这项措施  在用户界面  开始旋转之前  会得以实施。首先  我们  在源代码中  为layoutViewController类型的物件  添加 两个按钮。在layoutViewController.h这个文件中的@interface命令  和  @end命令之间  添加  下面两行语句:

接着  在layoutViewController.m这个文件中@implementation命令后面  添加  下面两行语句:

最后  在界面创建器中  将  用户界面中的两个按钮  分别  与  layoutViewController类型物件所包含的变量firstButton  和  secondButton  连接起来,具体的连接方法  在之前的文章中  提到过。这样  你  就可以在源代码中  控制  用户界面上的两个按钮了。

然后  我们  需要  在layoutViewController.m这个文件当中  添加  willAnimateRotationToInterfaceOrientation这项措施:

这项措施的第一个参数  toInterfaceOrientation  代表  当前设备转到的方向  或者  视图即将要转到的方向。if()语句  会判断  视图即将要转到的方向  是否是  横屏底部朝左  或者  横屏底部朝右。如果  视图即将要转到的方向  是  横屏底部朝左  或者  横屏底部朝右,则执行

如果  视图即将转到的方向  不是  横屏底部朝左  或者  横屏底部朝右,换句话说  就是  竖屏  或者  竖屏上下颠倒,那么  就执行:

在上面四行语句中  我们  调用了  CGRectMake()这个函数。调用  CGRectMake()这个函数时,需要向  其  提供  四个参数,它们  分别依次  是  横坐标、纵坐标、宽度、高度。CGRectMake()这个函数 执行结束后  会产生  一个你指定位置  和  尺寸的矩形。每个视图物件  都包含  一个变量frame,代表  这个视图物件的框架。我们  只要将  一个视图物件的框架frame  设定为  CGRectMake()函数生成的矩形,这个视图物件的位置  和  尺寸  就会变为  CGRectMake()这个函数所生成的矩形的位置  和  尺寸。

最后  别忘了  将  viewDidUnload这项措施  修改成  这样:

在编译、运行  这个程序之前,我们  要打开  layoutViewController.xib这个文件,将  视图  修改为  下面的样子:

编译  并且  运行  这个程序后,可以看到  这样的效果:

我们  将  iOS模拟器  旋转  到横屏模式  就可以看到  这样的效果:


你可能感兴趣的:(objective-c)