Mais conteúdo relacionado
Semelhante a 06 Subclassing UIView and UIScrollView (20)
06 Subclassing UIView and UIScrollView
- 1. ⼦子类化 UIView 和 UIScrollView
范圣刚,princetoad@gmail.com,www.tfan.org
- 2. 什么是 view?
• 我们在前⾯面创建过 UIButton,UILabel等,但是究
竟什么是 view?
• ⼀一个 view 是 UIView 或者它的某⼀一⼦子类的实例
• view 知道如何把它⾃自⼰己绘制到应⽤用程序窗⼝口上(⼀一个
UIWindow 的实例)
• view 存在于 view 的层次结构中 view hierarchy。view
hierarchy 的根是应⽤用程序窗⼝口
• view 要处理事件,⽐比如触控事件
- 7. UIWindow
• UIWindow 是 UIView 的⼦子类
• 每个应⽤用程序恰好有⼀一个 UIWindow 的实例作为
在应⽤用中所有视图的容器,当应⽤用启动的时候窗
⼝口被创建
• HypnosisterAppDelegate.m 中的
application:didFinishLaunchingWithOptions: ⽅方
法中创建 UIWindow 对象并发送消息
makeKeyAndVisible
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- 8. subview
• window 被放到屏幕上以后,就可以在它上⾯面增加
其他 view,这样的 view 就叫做 window 的
subview
• 作为 window 的 subview 的 view 也可以具有
subviews,结果就形成了⼀一个视图对象的层次结
构
• 当且仅当⼀一个视图被添加到这个层次结构以后才
会在屏幕上显⽰示,⽆无论它是作为 window 的⼀一个
subview,还是作为另外⼀一个已经添加到 window
的 view 的 subview
• 因此,window 是 view hierarchy 的 root
- 11. ⽤用户界⾯面⽣生成
• 创建每⼀一个 view 的图像并且把每⼀一个 view 加到
view hierarchy
• 类似 UIButton,MKMapView 以及 UITextField 这些
(Apple本⾝身提供的)已经知道它们的图像看起来
是什么样⼦子
• 另外⼀一种情况是我们需要创建⼀一个⾃自定义的视图
对象并且编写代码来创建它的图像
- 13. • ⼦子类化 UIView,并且⾃自定义⼦子类的图像
• 创建⼀一个类 HypnosisView, 从 UIView 继承
• 在 HypnosisterAppDelegate.m 中引⼊入 HypnosisView.h
头⽂文件
• 在 application:didFinishLaunchingWithOptions: 中创建
HypnosisView 的实例并把它作为 window 的 subview
添加到 view hierarchy 中
- 14. 创建 HypnosisView 的实例并添
加到UIWindow
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]
bounds]];
CGRect viewFrame = CGRectMake(160, 240, 100, 150);
HypnosisView *view = [[HypnosisView alloc] initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[[self window] addSubview:view];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- 15. subview 和 superview
• 红⾊色的 HypnosisView 实例
在⽩白⾊色的 UIWindow 之上绘
制;HypnosisView 实例是
UIWindow 的 subview
• 把⼀一个 view 作为另外⼀一个
view 的 subview 添加时,反
向关系同时也⾃自动建⽴立了,
HypnosisView 的 superview
是 UIWindow
• XIB ⽂文件和编程创建
- 16. initWithFrame:
• 当编程创建⼀一个 view 时,我们使⽤用 alloc 和⼀一个
initializer message,就像我们创建任何其他对象
⼀一样
• UIView 的 designated initializer,同样也是
HypnosisView的,是:initWithFrame:
• initWithFrame: 采⽤用 CGRect 结构作为参数,这个
CGRect 就是 view 的边框
- 17. view 的 frame
• 每个视图实例都有⼀一个 frame 矩形
• 视图的 frame 指定了视图的⼤大⼩小和其相对于它的
superview 的位置
• frame 由 CGRect 结构体表⽰示,并且包含成员 origin
和 size。这些成员也是结构体
• orgin 是 CGPoint 类型,包含两个 float 成员:x 和 y
• size 是 CGSize 类型,包含两个 float 成员: width
和 height
• 结构体 structure 并不是 objective-c 对象,因此不
能给它们发送消息
- 19. 再画⼀一个 HypnosisView 作为 Window的 subview
// 再创建⼀一个 HypnosisView
CGRect anotherFrame = CGRectMake(20, 30, 50, 50);
HypnosisView *anotherView = [[HypnosisView alloc] initWithFrame:anotherFrame];
[anotherView setBackgroundColor:[UIColor blueColor]];
[[self window] addSubview:anotherView];
- 21. 将⼀一个 HypnosisView 作为另⼀一个 HypnosisView 的
subview
• ⼀一个 view 的 frame 是
相对于它的 superview
的,⽽而不是 window
[[self window] addSubview:anotherView];
[view addSubview:anotherView];
- 24. • 截⾄至⺫⽬目前,我们创建了⼀一个 UIView 的⼦子类,创建
了两个实例,把它们插⼊入到了 view hierarchy
• 我们给这两个实例不同的 backgroundColor 以便
区分它们在屏幕上的位置和⼤大⼩小。组成 iOS 所有
界⾯面的 view,要能够绘制更多,⽽而不仅仅是带颜
⾊色的矩形
• 使视图变得有趣的绘制都发⽣生在 UIView 的
drawRect: ⽅方法中
• 默认情况下,drawRect: 什么都不做。UIView ⼦子类
通过重写这个⽅方法来实现⾃自定义绘制。
- 25. Core Graphic framework
• 在我们重写 drawRect: 时,我们发出创建 UIView
⼦子类的实例图像的绘制指令,这些绘制指令都来
⾃自 Core Graphics framework。
• 这个框架在创建新项⺫⽬目时被⾃自动添加到
application target
- 26. 绘制上下⽂文(drawing context)
• 重写 drawRect: 的第⼀一步是获取 drawing context
(绘制上下⽂文)的指针
• 绘制上下⽂文维护绘制的状态(例如当前绘制的颜
⾊色和画笔的厚度)和执⾏行绘制操作
• 绘制操作会使⽤用当前的绘制状态进⾏行绘制
• 在 drawRect: 结束时,上下⽂文⽣生成的图像就变成了
view 的图像
- 27. CGContextRef
• CGContextRef 被定义为 CGContext * - 指向
CGContext 的指针
• Ref 后缀使得很容易区分指向 C 结构体的指针和指
向 Objective-C 对象的指针
• 这⾥里的 ctx 指向了当前的绘制上下⽂文
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
}
- 28. bounds
• view 的图像和它出现在屏幕上是⼀一样⼤大⼩小,也就
是说和 view 的 frame ⼤大⼩小⼀一致
• frame 描述了 view 相对于 view 的 superview 的⼤大
⼩小
• UIView 的名为 bounds 的 CGRect 属性给出了视图
和它的 superview ⽆无关的⼤大⼩小
• 在 CGContextRef 上执⾏行的绘制操作必须落在
bounds 矩形区域内,否则会被剪切到这个矩形区
域
- 29. 在 bounds 矩形中⼼心绘制⼀一个圆形
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect bounds = [self bounds];
// 计算出 bounds 矩形的中⼼心
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0;
// 圆的半径应该是和 view 的⼤大⼩小⼏几乎⼀一样的
float maxRadius = hypot(bounds.size.width, bounds.size.height) / 4.0;
// 线条宽度应该是 10pt 宽
CGContextSetLineWidth(ctx, 10);
// 线条的颜⾊色应该是灰⾊色(red/green/blue = 0.6, alpha = 1.0)
CGContextSetRGBStrokeColor(ctx, 0.6, 0.6, 0.6, 1.0);
// 增加⼀一个矩形到上下⽂文 - 这不会真正绘制矩形
CGContextAddArc(ctx, center.x, center.y, maxRadius, 0.0, M_PI * 2.0, YES);
// 执⾏行绘制指令;使⽤用当前状态绘制当前形状
CGContextStrokePath(ctx);
}
- 31. backgroundColor
• 在 HyposisterAppDelegate.m 中,移除设置 view
的背景颜⾊色的代码
• 在 HypnosisView.m 中,重写 initWithFrame: 来设
置每个 HyposisView 的背景颜⾊色为 clear
HypnosisView *view = [[HypnosisView alloc]
initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[[self window] addSubview:view];
CGRect anotherFrame = CGRectMake(20, 30, 50, 50);
HypnosisView *anotherView = [[HypnosisView alloc]
initWithFrame:anotherFrame];
[anotherView setBackgroundColor:[UIColor blueColor]];
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
- 34. Core Graphics
• 以 CG 开头的函数和类型都来⾃自于 Core Graphics
framework, ⼀一套⽤用于 2D 绘图的 C 语⾔言 API
• Core Graphics framework 的中⼼心是 CGContextRef: 所
有其他的 Core Graphics 函数和类型都以某种⽅方式和
绘制上下⽂文进⾏行交互,然后由上下⽂文来创建图像
• 前⾯面⽤用到的 Core Graphics 函数:
• 使⽤用 CGContextSetLineWidth 设置绘制状态
• 使⽤用 CGContextSetRGBStrokeColor 设置描边颜⾊色
• 使⽤用 CGContextAddArc 增加⼀一个 path 到上下⽂文(Arc
只是 path 的⼀一种)
- 36. 绘制⼀一系列的同⼼心圆
• ⼀一个绘制操作完成后,当前路径就被从上下⽂文中
移除
• 这样,要绘制多于⼀一个圆形的话,就需要为每个
圆形添加⼀一个路径到上下⽂文
// 圆的半径应该是和 view 的⼤大⼩小⼏几乎⼀一样的
// float maxRadius = hypot(bounds.size.width, bounds.size.height) / 4.0;
float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;
// 线条宽度应该是 10pt 宽
CGContextSetLineWidth(ctx, 10);
// 线条的颜⾊色应该是灰⾊色(red/green/blue = 0.6, alpha = 1.0)
CGContextSetRGBStrokeColor(ctx, 0.6, 0.6, 0.6, 1.0);
for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20) {
CGContextAddArc(ctx, center.x, center.y, currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(ctx);
}
- 38. 修改 didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication
*)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen]
bounds]];
// 创建⼀一个 HypnosisView,⼤大⼩小和屏幕⼤大⼩小⼀一样
⼤大
HypnosisView *view = [[HypnosisView
alloc] initWithFrame:[[self window]
bounds]];
[[self window] addSubview:view];
// Override point for customization
after application launch.
self.window.backgroundColor = [UIColor
whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- 40. UIColor
• 例如:UIColor,⼀一个 UIColor 的实例表⽰示⼀一种颜
⾊色,可以⽤用来设置上下⽂文当前⽤用来绘制的颜⾊色
• 可以把 CGContextSetRGBStrokeColor(ctx, 0.6, 0.6, 0.6,
1.0) 替换为 [[UIColor colorWithRed: 0.6 green:0.6 blue:
0.6 alpha:1] setStroke];
• UIColor 也预先准备了很多常⽤用的颜⾊色供使⽤用,可
以把上⾯面的代码改成:[[UIColor lightGrayColor]
setStroke];
CGContextSetRGBStrokeColor(ctx, 0.6, 0.6, 0.6, 1.0);
[[UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1] setStroke];
- 41. NSString
• NSString 能够绘制到 CGContextRef
• 发送 drawInRect:withFont: 消息给⼀一个 NSString 将
会使⽤用给定的字体把这个字符串绘制到当前上下
⽂文给定的矩形内
• 在 HyposisView.m 中的 drawRect: 中代码的末尾增
加⼀一段代码
NSString *text = @"你快被催眠了.";
UIFont *font = [UIFont boldSystemFontOfSize:28];
CGRect textRect;
textRect.size = [text sizeWithFont:font];
textRect.origin.x = center.x - textRect.size.width / 2.0;
textRect.origin.y = center.y - textRect.size.height / 2.0;
[[UIColor blackColor] setFill];
[text drawInRect:textRect withFont:font];
- 43. 使⽤用阴影
// 设置当前上下⽂文填充⾊色为⿊黑⾊色
[[UIColor blackColor] setFill];
// 增加阴影。阴影将会向右移动4个points,向下移动3个points
CGSize offset = CGSizeMake(4, 3);
// 阴影颜⾊色使⽤用深灰⾊色
CGColorRef color = [[UIColor darkGrayColor] CGColor];
// 使⽤用这些参数设置上下⽂文的阴影,后续绘制都会使⽤用阴影 (blur,模
糊,2.0)
CGContextSetShadowWithColor(ctx, offset, 2.0, color);
// 绘制字符串
[text drawInRect:textRect withFont:font];
- 47. • 当⼀一个 UIView 实例收到 setNeedsDisplay 消息
时,会重绘它的图像
• 当视图⼦子类可绘制内容变更时,会给⾃自⾝身发送
setNeedsDisplay 消息
• 例如⼀一个 UILabel 当它被发送 setText: 消息时会为重
新显⽰示⽽而标记⾃自⾝身(如果显⽰示的⽂文本变更的话必须要
重新绘制图像)
• 重绘操作不会⽴立即执⾏行,⽽而是在 run loop 中进⾏行
• 重绘和组合
- 49. 增加 circleColor 属性
• HypnosisView.h 中声明 circleColor 属性
• HypnosisView.m 中 synthesize 这个属性
• 更新 initWithFrame: ⽅方法创建⼀一个默认的
circleColor
• 在 drawRect: 中设置上下⽂文描边颜⾊色使⽤用
circleColor ⽽而不是 light gray
- 50. 增加 circleColor (代码)
@interface HypnosisView : UIView
@property (nonatomic, strong) UIColor *circleColor;
@end
@implementation HypnosisView
@synthesize circleColor;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor clearColor]];
[self setCircleColor:[UIColor lightGrayColor]];
}
return self;
}
CGContextSetLineWidth(ctx, 10);
[[self circleColor] setStroke];
for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20) {
CGContextAddArc(ctx, center.x, center.y, currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(ctx);
}
- 52. • UIView 的超类 UIResponder 的实例,可以在设备
被晃动或者键盘上的按键被按下时成为 window
的 first responder 并将接收事件
• 下⾯面我们把 HypnosisView 的实例作为 Hypnosister
window 的 first responder ,晃动设备将发送消息
给 HypnosisView,并且这个⽅方法将改变它的
circleColor
- 53. becomeFirstResponder
• 在 HypnosisterAppDelegate.m 中告诉
HypnosisView 实例成为 first responder
• becomeFirstResponder ⽅方法返回⼀一个布尔值,标明
接收对象是否成功的变成了 window 的 first
responder
BOOL success = [view becomeFirstResponder];
if (success) {
NSLog(@"HypnosisView 成为 first responder");
} else {
NSLog(@"⽆无法成为 first responder");
}
- 54. canBecomeFirstResponder
• ⼤大多数 UIResponder 对象收到
becomeFirstResponder 时返回 NO
• 因为⼤大多数的视图,默认情况下只关⼼心和它们关联
的事件,并且它们(⼏几乎)总有机会处理这些事件
• 举例来说,不管谁是 first responder ⼀一个被点击的
UIButton 总会被发送消息
• 所以,⼀一个 responder 对象必须显式表明它希望变
成 first responder
• 在 HypnosisView.m 中重写UIResponder 的
canBecomeFirstResponder 来返回 YES
- (BOOL)canBecomeFirstResponder{ return YES; }
- 55. 动作事件⽅方法(motion event methods)
• 接收事件的⽅方法也是在 UIResponder 中实现的,
为了实例能够响应事件它们也必须在 UIResponder
的⼦子类中重写
• 为了处理 shakes,在 UIResponder ⼦子类中重写的
⽅方法被称为 motion event methods(动作事件⽅方
法),其声明类似:
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
- 56. motionBegan:withEvent:
• 为了让 HypnosisView 能够知道⽤用户开始摇动设备
并且采取⾏行动,必须实现 motionBegan:withEvent:
⽅方法
• 在 HypnosisView.m 中重写这个⽅方法以便开始摇动
的时候改变 circleColor
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent
*)event
{
NSLog(@"设备开始摇动");
[self setCircleColor:[UIColor redColor]];
}
- 57. 发送 setNeedsDisplay 消息
• 当 HypnosisView 的 circleColor 改变时,实例变量
circleColor 被设置指向⼀一个新的 UIColor 实例
• 但是当这些发⽣生时,我们并没有告诉
HypnosisView 它需要重新绘制它的图像;我们必
须在 HypnosisView 改变了它的 circleColor 后给它
发送 setNeedsDisplay 消息
• 在 HypnosisView.m 中,实现 setCircleColor: 以在变
更 circleColor 实例变量后发送这个消息
• 此时再运⾏行应⽤用,摇动设备,圆形就变成了红⾊色
- (void)setCircleColor:(UIColor *)clr
{
circleColor = clr;
[self setNeedsDisplay];
}
- 58. UIEventSubtype
• UIEventSubtype 持有触发这个⽅方法的动作事件的
类型。根据类型定义,处理 shake 事件外还可能
会有其他事件也触发这个⽅方法
• 在 HypnosisView.m 中 增加⼀一⾏行⽤用于判断的代码:
if (motion == UIEventSubtypeMotionShake)
typedef NS_ENUM(NSInteger, UIEventSubtype) {
UIEventSubtypeNone = 0,
UIEventSubtypeMotionShake = 1,
UIEventSubtypeRemoteControlPlay = 100,
UIEventSubtypeRemoteControlPause = 101,
UIEventSubtypeRemoteControlStop = 102,
UIEventSubtypeRemoteControlTogglePlayPause = 103,
UIEventSubtypeRemoteControlNextTrack = 104,
UIEventSubtypeRemoteControlPreviousTrack = 105,
UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
UIEventSubtypeRemoteControlEndSeekingBackward = 107,
UIEventSubtypeRemoteControlBeginSeekingForward = 108,
UIEventSubtypeRemoteControlEndSeekingForward = 109,
};
- 62. contentSize
• 滚动视图⼀一般⽤用于⽐比屏幕⼤大的视图,滚动视图绘
制它的 subview 的⼀一个矩形部分,在滚动视图上
移动你的⼿手指或者平移时,改变的是 subview 的
矩形的位置
• 可以把滚动视图看作是⼀一个观察⼝口(view
port),滚动视图的⼤大⼩小就是这个观察⼝口的⼤大⼩小
• 能够查看的区域⼤大⼩小是 UIScrollView 的 contentSize,
⼀一般就是UIScrollView 的 subview 的⼤大⼩小
- 64. 超⼤大号的 HypnosisView
• 在 HypnosisterAppDelegate.m 中创建⼀一个超⼤大号
的 HypnosisView
• 把⼤大号的 HypnosisView 放到⼀一个 scroll view 中
• 把 scroll view 添加到 window
- 65. 超⼤大号的 HypnosisView(代码)
// 创建⼀一个和 window ⼀一样⼤大的 UIScrollView
CGRect screenRect = [[self window] bounds];
UIScrollView *scrollView = [[UIScrollView alloc]
initWithFrame:screenRect];
[[self window] addSubview:scrollView];
// 创建⼀一个是屏幕两倍⼤大的 HypnosisView,并添加到scroll view
CGRect bigRect = screenRect;
bigRect.size.width *= 2.0;
bigRect.size.height *= 2.0;
HypnosisView *view = [[HypnosisView alloc]
initWithFrame:bigRect];
// 把 HypnosisView 作为 subview 添加到 scrollview,⽽而不是 window
[scrollView addSubview:view];
// 告诉 scrollview 它的区域有多⼤大
[scrollView setContentSize:bigRect.size];
- 67. 平移和分⻚页(panning and paging)
• 前⾯面我们⽤用 scroll view 来移动特别⼤大的 view
• scroll view 也可以⽤用来在⼀一些不同的 view 实例之
间进⾏行平移
• ⽐比如我们有两个屏幕⼤大⼩小的视图,⽤用户可以在它
们之间平移
• 我们把前⾯面例⼦子中的 HypnosisView 再缩回跟原来
屏幕⼀一样⼤大⼩小,并且增加另外⼀一个同样⼤大⼩小的
HypnosisView 作为 UIScrollView 的 subview
• 同样,把 contentSize 设成屏幕宽度的两倍,⾼高度
⼀一样
- 68. 平移(代码)
// 创建⼀一个和 window ⼀一样⼤大的 UIScrollView
CGRect screenRect = [[self window] bounds];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];
[[self window] addSubview:scrollView];
CGRect bigRect = screenRect;
bigRect.size.width *= 2.0;
// 把⾼高度改成和屏幕⼀一样
// bigRect.size.height *= 2.0;
// HypnosisView *view = [[HypnosisView alloc] initWithFrame:bigRect];
HypnosisView *view = [[HypnosisView alloc] initWithFrame:screenRect];
// 把 HypnosisView 作为 subview 添加到 scrollview,⽽而不是 window
[scrollView addSubview:view];
// 把另⼀一个 HypnosisView 的矩形移动右边屏幕外
screenRect.origin.x = screenRect.size.width;
// 创建另外⼀一个 HypnosisView
HypnosisView *anotherView = [[HypnosisView alloc] initWithFrame:screenRect];
[scrollView addSubview:anotherView];
// 同样告诉 scrollview 它的区域有多⼤大
[scrollView setContentSize:bigRect.size];
- 70. setPagingEnable:
• 前⾯面移动视图的时候可以停在两个 HypnosisView 之间
• 要强制滚动视图的观察⼝口捕捉这些视图之⼀一,在
HypnosisterAppDelegate.m 中为 scroll view 打开
paging(分⻚页)
• 这样再平移到两个视图中间时,就会⾃自动滚动到其中
⼀一个视图
• paging 通过滚动视图的 contentSize / bounds 来分成
同样⼤大⼩小的 section 进⾏行显⽰示
CGRect screenRect = [[self window] bounds];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];
// 打开 paging
[scrollView setPagingEnabled:YES];
[[self window] addSubview:scrollView];
- 71. 缩放(Zooming)
• UIScrollView 还以可以放⼤大或者缩⼩小其内容
• 要进⾏行缩放,scroll view 需要知道最⼩小和最⼤大缩放
级别,⽽而且需要知道要进⾏行缩放的视图
• 把 HypnosisterAppDelegate.m 中的另⼀一个
HypnosisView 去掉,同时把 UIScrollView 的
contentSize 改回屏幕⼤大⼩小
• 然后禁⽤用 paging,设置 zoom 属性,设置
UIScrollView 的 delegate
- 72. Zooming(代码)
CGRect screenRect = [[self window] bounds];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:screenRect];
// 设置缩放属性
[scrollView setMinimumZoomScale:1.0];
[scrollView setMaximumZoomScale:5.0];
// 设置 scrollView 的 delegate
[scrollView setDelegate:self];
[[self window] addSubview:scrollView];
CGRect bigRect = screenRect;
HypnosisView *view = [[HypnosisView alloc] initWithFrame:screenRect];
// 把 HypnosisView 作为 subview 添加到 scrollview,⽽而不是 window
[scrollView addSubview:view];
// 同样告诉 scrollview 它的区域有多⼤大(现在 scroll view 是屏幕⼤大⼩小)
[scrollView setContentSize:bigRect.size];
- 74. 实现 viewForZoomingInScrollView
• 在 HypnosisterAppDelegate.h 中,声明
HypnosisterAppDelegate 遵守
UIScrollViewDelegate
• 在 HypnosisterAppDelegate 中把指向
HypnosisView 的本地变量改成实例变量,以便在
viewForZoomingInScrollView: 中可以访问
• 实现 viewForZoomingInScroolView 来返回这个
view
- 75. 实现 viewForZoomingInScrollView(代码)
#import <UIKit/UIKit.h>
// 导⼊入 HypnosisView 头⽂文件
#import "HypnosisView.h"
@interface HypnosisterAppDelegate : UIResponder <UIApplicationDelegate,
UIScrollViewDelegate>
{
HypnosisView *view;
}
@property (strong, nonatomic) UIWindow *window;
@end
// HypnosisView *view = [[HypnosisView alloc] initWithFrame:screenRect];
view = [[HypnosisView alloc] initWithFrame:screenRect];
[scrollView addSubview:view];
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return view;
}
- 77. 隐藏状态栏
• 在窗⼝口可⻅见前隐藏状态栏
• 在 HypnosisterAppDelegate.m 中的
application:didFinishLaunchingWithOptions: 接近
顶部的地⽅方添加⼀一⾏行代码
• 再构建并运⾏行时,会发现状态栏在应⽤用程序启动
以后会逐渐消失(fading out)
// 隐藏状态栏 status bar
[[UIApplication sharedApplication]
setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationFade];