首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》5.3 使用UIScrollView

关灯直达底部

本节将为Hypnosister应用添加一个UIScrollView对象,使其成为应用窗口的子视图,然后再将BNRHypnosisView作为子视图加入UIScrollView对象(见图5-2)。

图5-2 加入UIScrollView之后的视图层次结构

通常情况下,UIScrollView对象适用于那些尺寸大于屏幕的视图。当某个视图是UIScrollView对象的子视图时,该对象会画出该视图的某块区域(形状为矩形)。当用户按住这块矩形区域并移动手指(即拖动,pan)时,UIScrollView对象会改变该矩形所显示的子视图区域。读者可以将UIScrollView对象看成是镜头,而其子视图是拍摄的景观。这里移动的是“镜头”,而不是“景观”(见图5-3)。UIScrollView对象的尺寸就是这个“镜头”的尺寸,而其能够拍摄的范围是由其属性contentSize决定的。通常情况下,contentSize的数值就是子视图的尺寸。

UIScrollView是UIView的子类,同样可以使用initWithFrame:消息初始化,还可以将其作为子视图添加到其他视图中。

图5-3 UIScrollView对象及其contentSize

在BNRAppDelegate.m中,创建一个有着超大尺寸的BNRHypnosisView对象并将其加入一个UIScrollView对象,然后将这个UIScrollView对象加入窗口,代码如下:

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

self.window = [[UIWindow alloc] initWithFrame:

[[UIScreen mainScreen] bounds]];

// 在这里添加应用启动后的初始化代码

CGRect firstFrame = self.window.bounds;

BNRHypnosisView *firstView = [[BNRHypnosisView alloc]

initWithFrame:firstFrame];

[self.window addSubview:firstView];

// 创建两个CGRect结构分别作为UIScrollView对象和BNRHypnosisView对象的frame

CGRect screenRect = self.window.bounds;

CGRect bigRect = screenRect;

bigRect.size.width *= 2.0;

bigRect.size.height *= 2.0;

// 创建一个UIScrollView对象,将其尺寸设置为窗口大小

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];

[self.window addSubview:scrollView];

// 创建一个有着超大尺寸的BNRHypnosisView对象并将其加入UIScrollView对象

BNRHypnosisView *hypnosisView = [[BNRHypnosisView alloc]

initWithFrame:bigRect];

[scrollView addSubview:hypnosisView];

// 告诉UIScrollView对象/"取景/"范围有多大

scrollView.contentSize = bigRect.size;

self.window.backgroundColor = [UIColor whiteColor];

构建并运行应用,可以上、下、左、右拖动来查看超大尺寸的BNRHypnosisView对象的其余部分(见图5-4)。

图5-4 BNRHypnosisView的右上角

移动BNRHypnosisView对象的同时,圆形的颜色也会发生变化。这是由于移动视图时也会产生触摸事件,因此运行循环会将触摸事件发送给UIScrollView和BNRHypnosisView。第13章会介绍如何检测和处理“tap(点击)”手势,用来区别触摸手势和移动手势。

使用UIScrollView还可以实现“Pinch-to-zoom(捏合缩放)”功能。虽然只需要添加几行代码就可以实现该功能,但是这些代码涉及第7章中的技术。为Hypnosister添加捏合缩放功能是第7章的练习。

拖动与分页

UIScrollView对象还可以滑动显示所有加入UIScrollView对象的子视图。

在BNRAppDelegate.m中,将BNRHypnosisView对象的尺寸改回与屏幕的尺寸相同,然后再创建一个BNRHypnosisView对象,将其尺寸也设置为与屏幕的尺寸相同并加入UIScrollView对象。此外,还要将UIScrollView对象的contentSize的宽度设置为屏幕宽度的2倍,高度不变,代码如下:

// 创建两个CGRect结构分别作为UIScrollView对象和BNRHypnosisView对象的frame

CGRect screenRect = self.window.bounds;

CGRect bigRect = screenRect;

bigRect.size.width *= 2.0;

bigRect.size.height *= 2.0;

// 创建一个UIScrollView对象,将其尺寸设置为窗口大小

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];

[self.window addSubview:scrollView];

// 创建一个有着超大尺寸的BNRHypnosisView对象并将其加入UIScrollView对象

BNRHypnosisView *hypnosisView = [[BNRHypnosisView alloc]

initWithFrame:bigRect];

// 创建一个大小与屏幕相同的BNRHypnosisView对象并将其加入UIScrollView对象

BNRHypnosisView *hypnosisView = [[BNRHypnosisView alloc]

initWithFrame:screenRect];

[scrollView addSubview:hypnosisView];

// 创建第二个大小与屏幕相同的BNRHypnosisView对象并放置在第一个BNRHypnosisView

// 对象的右侧,使其刚好移出屏幕外

screenRect.origin.x += screenRect.size.width;

BNRHypnosisView *anotherView = [[BNRHypnosisView alloc]

initWithFrame:screenRect];

[scrollView addSubview:anotherView];

// 告诉UIScrollView对象/"取景/"范围有多大

scrollView.contentSize = bigRect.size;

构建并运行应用,按从左向右的方向拖动屏幕,应该能先后看到两个BNRHypnosisView对象。请注意,UIScrollView对象有可能同时显示两个BNRHypnosisView对象的部分区域,即两个BNRHypnosisView对象的连接部分(见图5-5)。

图5-5 UIScrollView显示两个BNRHypnosisView的连接部分

某些情况下,这种行为是符合预期的。但是有时也要让UIScrollView对象的“镜头”的边和其显示的某个视图的边对齐。为此,要将UIScrollView对象的pagingEnabled设置为YES。在BNRAppDelegate.m中将scrollView的pagingEnabled设置为YES,代码如下:

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];

[scrollView setPagingEnabled:YES];

[[self window] addSubview:scrollView];

构建并运行应用,拖动屏幕直到能看到两个BNRHypnosisView对象的连接部分,然后松开手指。UIScrollView对象应该会自动将“镜头”切换到其中一个BNRHypnosisView对象上。UIScrollView对象的分页实现原理是:UIScrollView对象会根据其bounds的尺寸,将contentSize分割为尺寸相同的多个区域。拖动结束后,UIScrollView实例会自动滚动并只显示其中的一个区域。