1、IOS应用开发教程,QQ学习群:262779381,http:/,第五章 IOS基础界面编程,QQ学习群:262779381,教学目标: 1、掌握IOS开发基本界面布局。 2、掌握UIWindow与UIView的关系,并掌握UIView常见子类的使用方法。 3、掌握IOS中的坐标系统。 4、IOS中常用控件的使用。,QQ学习群:262779381,5.1UIWindow和UIView,在IOS平台上运行的应用程序都有一个UIApplication类的对象,UIApplication类继承域UIResponder类,它是IOS应用程序的起点,并且负责初始化和显示UIWindow,它还将接受事件,
2、通过委托“UIAppliactionDelegate”来处理,还有一重要的功能就是帮助管理应用程序的生命周期。,QQ学习群:262779381,应用程序状态表,QQ学习群:262779381,QQ学习群:262779381,正如在上表与图中看到的几个程序状态,系统要做出不同的事件处理。UIApplication的一个主要人任务就是处理用户事件,它会创建一个队列,将所有用户事件都放入队列中,在处理过程中,它会发送当前事件到一个合适处理事件的控件。换句话说,UIApplication类并不具体实现某项功能,它只是负责监听事件,当需要实际完成工作时,就将工作分配给UIApplicationDeleg
3、ate去完成。而在UIApplicationDelegate中定义了很多协议需要实现。这些协议中定义好的方法就是UIApplication对象监听到系统变化的时候通知UIApplication对象代理类执行的相应方法。,QQ学习群:262779381,1. -(void)applicationWillResignActive:(UIApplication*)application 此方法在应用程序将要进入到非活动状态执行,在此期间,应用程序不接受消 息。 2. -(void)applicationDidBecomeActive:(UIApplication*)application此方法在应用
4、程序将要进入到活动状态执行,和第一个方法相反。 3. -(void)applicationDidReceiveMemoryWarning:(UIApplication*)application执行这个方法可以进行内存清理防止程序被太多内存所占用而导致终止。 4. -(void)applicationDidFinishLaunching:(UIApplication*)application 这个方法的功能是在程序载入后可以执行一些用户需要的操作。 5-(void)applicationDidEnterBackground:(UIApplication*)application这个方法是在程序被
5、推送到后台的时候调用。 注意:若在代码中提示release错误,说明程序使用了ARC(Automatic Reference Counting)机制,只需要去掉release方法,或者勾选去除ARC机制,去除方法在Building Settings中的Apple LLVM6.0 - Language-Objective-C。,QQ学习群:262779381,#import “AppDelegate.h“ implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWi
6、thOptions:(NSDictionary *)launchOptions self.window = UIWindow alloc initWithFrame:UIScreen mainScreen bounds;/ Override point for customization after application launch.self.window.backgroundColor = UIColor cyanColor;self.window makeKeyAndVisible;return YES; - (void)applicationWillResignActive:(UIA
7、pplication *)application NSLog(“应用正处于非活动状态!“); - (void)applicationDidEnterBackground:(UIApplication *)application NSLog(“应用已经在后台!“); - (void)applicationWillEnterForeground:(UIApplication *)application NSLog(“应用正处前台!“); - (void)applicationDidBecomeActive:(UIApplication *)application NSLog(“应用正处于活动状态!
8、“); - (void)applicationWillTerminate:(UIApplication *)application NSLog(“应用将被终止!“); end,QQ学习群:262779381,我们知道在Mac OS中,是支持多窗口任务的,但是在IOS应用程序中一般只有一个窗口,表示为一个UIWindow类,IOS是单窗口多视图的一个系统。UIWindow类一个应用程序最为基础的一个类,这就像我们的一个画布,UIWindow就是最底层的画布,我们需要做的就是往窗口中加入各种视图,来完善我们的“绘画作品”。UIWindow其实也是一个视图,因为它的父类是UIView。我们在创建一个
9、应用程序时,系统会自动为我们创建一个UIWindow。,QQ学习群:262779381,5.1.1窗口和视图,- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions self.window = UIWindow alloc initWithFrame:UIScreen mainScreen bounds autorelease;self.window.backgroundColor = UIColor cyanColor;self.w
10、indow makeKeyAndVisible;return YES; 在应用程序载入的时候,系统就创建了一个UIWindow窗口作为基本的窗口,并设置了他尺寸等于物理设备的尺寸,通过UIScreen mainScreen bounds这条语句能获得不同设备当前的屏幕尺寸,可以通用与多种设备之间。最后让窗口显示在屏幕上。我们一般不用去考虑对窗口的操作,一般的操作都建立在视图上,但我们要了解窗口和视图之间的框架结构关系。,QQ学习群:262779381,视图是UIView类的实例,它负责在屏幕上绘制一个矩形区域。视图的作用主要体现在用户界面的显示以及相应用户界面交互上。UIView有父视图(su
11、perview)和子视图(subview)属性,而通过定义这两个属性,可以建立视图之间的层次关系,并且这两个属性还关系到视图坐标的确定。 有3个和视图相关的结构体,分别是: CGPointx,y 代表了所在视图的坐标信息 CGSizewidth,height 代表了所在视图的大小信息 CGRectorigin,size所在视图所在坐标(视图左上角的点)和大小信息 还有3个相对应的函数 CGPointMake(x,y) 声明了位置信息 CGSizeMake(width,height) 声明了大小信息 CGRectMake(x,y,width,height) 声明了位置和大小信息,QQ学习群:26
12、2779381,- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions /创建窗口 self.window = UIWindow alloc initWithFrame:UIScreen mainScreen bounds autorelease; self.window.backgroundColor = UIColor cyanColor; /创建视图UIView *baseView = UIView allocinitWithF
13、rame:CGRectMake(10, 50, 300, 400);baseView.backgroundColor = UIColor blackColor;self.window addSubview:baseView;baseView release;self.window makeKeyAndVisible;return YES; ,QQ学习群:262779381,在使用UIView时,视图的坐标位置是一个很重要的信息,IOS中描述视图的坐标位置的属性有三个,分别是frame、bounds和center,初学者对前两个属性的使用上可能会有混淆,下面我们共同来学习一下IOS中坐标系统。
14、翻开IOS官方文档,我们可以看到对frame和bounds有如下的描述: Views location and size expressed in two waysFrame is in terms of superviews coordinate systemBounds is in terms of local coordinate system 我们来稍微解释一下它们的用法,frame属性是用来描述当前视图在父视图中的坐标位置和大小;bounds属性是描述当前视图在其自身坐标系统中的位置和大小。;而center属性则是描述了当前视图的中心点在其父视图中的位置。通过前面的描述,我们可以看出
15、虽然frame属性和bounds属性都是用来描述视图的大小(CGSize)和位置(CGPoint)的,但是他们各自描述的视图不同,换句话说,两者所在的坐标系是不同的。,QQ学习群:262779381,5.1.2IOS坐标系统,4. self.window = UIWindow alloc initWithFrame:UIScreen mainScreenbounds; 5. self.window.backgroundColor = UIColor whiteColor; 6. UIView *view1 = UIView allocinit; 7. view1.frame = CGRectM
16、ake(0, 0, 320, 570); 8. view1.backgroundColor = UIColor yellowColor; 9. self.window addSubview:view1; 10. view1 release; 11. UIView *view2 = UIView allocinitWithFrame:CGRectMake(100, 100, 120, 200); 12. view2.backgroundColor = UIColor cyanColor; 13. view1 addSubview:view2; 14. view2 release; 15. NSL
17、og(“view2.frame.origin.x = %.1f“,view2.frame.origin.x); 16. NSLog(“view2.frame.origin.y = %.1f“,view2.frame.origin.y); 17. NSLog(“view2.bounds.origin.x = %.1f“,view2.bounds.origin.x); 18. NSLog(“view2.bounds.origin.y = %.1f“,view2.bounds.origin.y); 19. UIView *view3 = UIView allocinitWithFrame:CGRec
18、tMake(0, 0, 100, 100); 20. view3.backgroundColor = UIColor blackColor; 21. view1 addSubview:view3; 22. view3 release; 23. NSLog(“view3.frame.origin.x = %.1f“,view3.frame.origin.x); 24. NSLog(“view3.frame.origin.y = %.1f“,view3.frame.origin.y); 25. NSLog(“view3.bounds.origin.x = %.1f“,view3.bounds.or
19、igin.x); 26. NSLog(“view3.bounds.origin.y = %.1f“,view3.bounds.origin.y); 27. self.window makeKeyAndVisible; 28.return YES;,QQ学习群:262779381,在这个程序中,我们定义了3个视图,view1的大小和iPhone4的屏幕大小相同,320*480,view2是view1的子视图,而view3则是view2的子视图。我们在前面说过,不同的视图层次关系会影响到视图的坐标位置,frame属性是以父视图的坐标位置为基准,我们看到view2的frame属性值是在父视图坐标为(
20、100,100)处,视图左上角的坐标点是(100,100),而bounds属性值是本视图坐标系的原点,所以是(0,0),所以bounds值都为本视图的原点坐标,所以都是(0,0)(也可以通过setbounds值来改变坐标的原点);我们再看view3的frame值,通过效果图可能更能够理解。这里需要注意内存管理的问题,在将view2添加到view1父视图中后,就可以对view2进行内存释放。,QQ学习群:262779381,我们看到view3的frame值是(0,0),但是它并不是出于屏幕的左上角,而是出于父视图坐标原点的位置,如果我改变view3的父视图,那它的位置就会有所改变。例如我将vie
21、w3的父视图设置为view2,将view1 addsubview:view3代码改为view2 addsubview:view3,坐标信息不改变,我们来看一下运行截图,效果如图5-4所示。我们看到虽然坐标的信息没有改变,但是因为父视图的改变,view3在屏幕中的位置也出现了变化,读者可以自行分析具体的变化情况。通常我们在设置视图的坐标位置时,是使用frame属性,bounds属性一般运用的比较少,通过frame属性操作,可以很清晰的体现出视图之间的层次关系。接下来我们就介绍视图之间的层次关系。,QQ学习群:262779381,我们把UIView层次结构看成数据结构中的树型结构,一个视图可以有多
22、个子视图,但是只能有一个父视图(基视图)。在我们添加子视图时,最后添加的视图会显示在最顶层,有点类似绘图工具中图层的概念。其实在前面的章节我们也了解了视图之间的层次关系,但是我们如果要对某个视图进行操作,或者改变层次之间的关系时,该怎么样操作呢?我们一一来讲解。 添加和移除子视图添加和移除子视图是大家最常使用的操作,在添加子视图时,会进行一次retain操作,而移除子视图则会调用release消息,这些是自动完成,我们只需要了解各个时刻的引用计数即可。前面我们提到了添加子视图的操作就是UIView addSubview:Subview,就不做过多的解释。下面我们在程序清单IOS Coordin
23、ate的基础上将view3从父视图中删除,并且来看一下引用计数的情况。,QQ学习群:262779381,5.1.3视图的层次关系及常用属性,1. UIView *view3 = UIView allocinitWithFrame:CGRectMake(0, 0, 100, 100); 2. view3.backgroundColor = UIColor blackColor; 3. view1 addSubview:view3; 4. NSLog(“view3.frame.origin.x = %.1f“,view3.frame.origin.x); 5. NSLog(“view3.frame
24、.origin.y = %.1f“,view3.frame.origin.y); 6. NSLog(“view3.bounds.origin.x = %.1f“,view3.bounds.origin.x); 7. NSLog(“view3.bounds.origin.y = %.1f“,view3.bounds.origin.y); 8. /retainCount = 2 9. NSLog(“retainCount = %d“,view3 retainCount); 10. view3 removeFromSuperview; 11. /retainCount = 1 12. NSLog(“
25、retainCount = %d“,view3 retainCount); 13. view1 release; 14. view2 release; 15. view3 release; 16. self.window makeKeyAndVisible; 17. return YES; 运行时屏幕中的视图只有view1和view2,view3已经从父视图中移除。我们也可以看到引用计数在移除前后的情况,要注意管理内存方面的问题。,QQ学习群:262779381,前移和后移视图我们还是以程序清单IOS Coordinate为例。如果想让view2显示在view3上面,则可以使用UIView b
26、ringSubviewToFront:Subview;命令将特定视图移到顶层。在父视图管理子视图过程中,是通过一个有序的数组存储着它的子视图,因此,数组存储的顺序就会影响到子视图的显示效果。我们现在等于是将特定的子视图向前移动了,所以它能显示在上一层。 1.UIView *view3 = UIView allocinitWithFrame:CGRectMake(50, 50, 100, 100); 2.view3.backgroundColor = UIColor blackColor; 3.view1 addSubview:view3; 4.NSLog(“view3.frame.origin
27、.x = %.1f“,view3.frame.origin.x); 5.NSLog(“view3.frame.origin.y = %.1f“,view3.frame.origin.y); 6.NSLog(“view3.bounds.origin.x = %.1f“,view3.bounds.origin.x); 7.NSLog(“view3.bounds.origin.y = %.1f“,view3.bounds.origin.y); 8.view1 bringSubviewToFront:view2; 9.view1 release; 10.view2 release; 11.view3
28、release; 12.self.window makeKeyAndVisible; 13.return YES;,QQ学习群:262779381,获取视图的index值对多个视图进行操作,首先要获取各个视图的index值,我们可以通过NSInteger index = UIView subviewsindexOfObject:Subview;语句来获取指定视图的index值。例如我们要获取view3的index值,可以在代码中添加这行代码。 2.UIView *view3 = UIView allocinitWithFrame:CGRectMake(50, 50, 100, 100); 3.
29、view3.backgroundColor = UIColor blackColor; 4.view1 addSubview:view3; 5.NSInteger index3 = view1 subviewsindexOfObject:view3; 6.NSLog(“index3 = %d“,index3); 7.view1 release; 8.view2 release; 9.view3 release; 10.self.window makeKeyAndVisible; 11.return YES;,QQ学习群:262779381,因为父视图管理子视图是通过数组的形式来管理,而view
30、3在父视图管理数组的第二个位置,所以它的index值为1(数组第一个元素从0开始)。通过这个index值我们可以对视图进行更多的操作,比如将新视图加到特定的视图上,我们可通过 View insertSubview:subview atIndex:0;命令将新视图添加到特定的视图上。获取所有子视图信息 父视图可以通过view1 subviews;命令将view1中所以的子视图的信息以数组的形式在控制台输出,我们可以来看view1的子视图信息。 控制台输出结果: “, “这里显示的是2个子视图的信息,它们都是继承于UIView类,我们可以通过frame值来观察具体视图的情况,layer属性我们在后
31、面的章节中会详细介绍,每一个视图都有一个layer层,还可以自行添加。,QQ学习群:262779381,设置tag值对视图进行操作通过设置视图的tag值,可以用来标示视图对象(整数),我们就能使用viewWithTag方法来更方便的对视图进行操作。Tag值的默认值是0,我们可以通过view.tag设置。接下来的例子我们做了一个小Demo,使用tag属性标记视图,然后通过按钮来改变视图的层次关系和颜色,也结合了上小节的内容。首先来看一下Demo中视图之间的层次关系,,QQ学习群:262779381,1.#import “AppDelegate.h“ 2.implementation AppDel
32、egate 3.- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 4. 5.self.window = UIWindow alloc initWithFrame:UIScreen mainScreen bounds autorelease; 6. self.window.backgroundColor = UIColor whiteColor; 7. /创建view1视图 8. UIView *view1 = UIView al
33、locinitWithFrame:CGRectMake(100, 100, 120, 160); 9. view1.tag = 1; 10. view1.backgroundColor = UIColor yellowColor; 11. self.window addSubview:view1; 12. /创建view2视图 13. UIView *view2 = UIView allocinitWithFrame:CGRectMake(110, 150, 100, 50); 14. view2.tag = 2; 15. view2.backgroundColor = UIColor blu
34、eColor; 16. self.window addSubview:view2; 17. /创建改变视图层次按钮1 18. UIButton *button1 = UIButton buttonWithType:UIButtonTypeRoundedRect; 19. button1.frame = CGRectMake(120, 270, 100, 30); 20. button1.backgroundColor = UIColor whiteColor; 21. button1 setTitle:“view1 top“ forState:UIControlStateNormal; 22.
35、 button1 addTarget:self action:selector(ViewChange1) 23. forControlEvents:UIControlEventTouchUpInside; 24. self.window addSubview:button1;,QQ学习群:262779381,25. /创建改变视图层次按钮2 26. UIButton *button2 = UIButton buttonWithType:UIButtonTypeRoundedRect; 27. button2.frame = CGRectMake(120, 320, 100, 30); 28.
36、button2.backgroundColor = UIColor whiteColor; 29. button2 setTitle:“view2 top“ forState:UIControlStateNormal; 30. button2 addTarget:self action:selector(ViewChange2) 31. forControlEvents:UIControlEventTouchUpInside; 32. self.window addSubview:button2; 33. /创建改变颜色按钮 34. UIButton *button3 = UIButton b
37、uttonWithType:UIButtonTypeRoundedRect; 35. button3.frame = CGRectMake(120, 370, 100, 30); 36. button3.backgroundColor = UIColor whiteColor; 37. button3 setTitle:“change color“ forState:UIControlStateNormal; 38. button3 addTarget:self action:selector(ViewChange3) 39. forControlEvents:UIControlEventTo
38、uchUpInside; 40. self.window addSubview:button3; 41. view1 release; 42. view2 release; 43. self.window makeKeyAndVisible; 44. return YES;,QQ学习群:262779381,46.- (void)ViewChange1 47. 48. UIView *view = self.window viewWithTag:1; 49. self.window bringSubviewToFront:view; 50. 51.- (void)ViewChange2 52.
39、53. UIView *view = self.window viewWithTag:2; 54. self.window bringSubviewToFront:view; 55. 56.- (void)ViewChange3 57. 58. UIView *view = self.window viewWithTag:2; 59. view.backgroundColor =UIColor greenColor; 60.,QQ学习群:262779381,我们定义了2个window的子视图,3个按钮的功能分别为,让view1在上层,让view2在上层,改变view2的颜色,如图5-7所示。这
40、些都是通过使用tag属性来获取当前的视图,通过这个例子我们也可以发现使用tag属性的优点。按钮控件我们还没有讲到,在后面的章节中会专门讲解控件的用法。现在在window窗口视图上有5个子视图,UIButton类也是继承于UIView类,我们可以通过view subviews命令来看一下所有子类信息的情况。因为这5个视图都加在窗口上,是window的子类,所以我们在定义它们的frame时要注意坐标要以父类的坐标系为基础。,QQ学习群:262779381,接下来我们介绍几个UIView常用的属性,读者可以在Xcode中查看相应的SDK可以查看到相应的属性和方法的用法。 1.clipsTobound
41、s属性,QQ学习群:262779381,通过设置Cliptobounds属性可以将子视图超出父视图的范围隐藏起来,它的默认值是NO。比如我们有两个视图,view2是view1的子视图,在定义它的大小和坐标时,使它的坐标不全在view1的范围内,则会有很大的区域超出了view1的范围,如果要隐藏这些超出的范围,我们可以使用view1.clipsTobounds = YES;语句来隐藏超出区域。通过效果截图可以清楚地观察设置clipsTobounds属性前后的效果。 2.alpha属性alpha属性在日常各种工具中都运用的比较广泛,它是用来设置视图的透明度,我们可以在初始化视图时对alpha属性进
42、行设置,也可以通过点语法设置alpha属性,但是我们要注意一个问题,如果设置父视图的alpha值为0.5,那么在父视图中所有的子视图也变为透明了,所以如果要对视图设置alpha值时,要注意这一个特性。在后面章节中实现动画效果时,我们也可以通过设置alpha值来实现视图的渐隐渐现的效果,会在后面进行详细的讲解。 3.hidden属性hidden属性从字面上看就能理解是用来隐藏视图的属性,设置hidden属性可以让视图隐藏,而alpha属性类似,如果设置了父视图的hidden值为YES,那么父视图上所有的子视图也跟着隐藏了。,QQ学习群:262779381,在前面章节中我们了解到UIView是iP
43、hone编程中一个很重要的概念,它完成了视图界面相关的工作,我们能在视图上进行各种可视化的操作,已达到用户所需要达到的效果。其实在UIView中还有一个很重要的属性,就是layer属性,每一个视图都有一个layer属性,也可以在基础的层(layer)上面在手动添加层。其实我们在前面的学习中一个不经意的地方遇到过layer,在上一节5.1.3中,我们在显示视图所有子视图的时候,我们在子视图中看到有layer,这说明layer是视图中另个一重要的概念。我们说UIView完成了可视化界面的绘制工作还是不准确的,因为真正绘图的部分是由CALayer类来完成的,而我们可以说UIView的功能是CALay
44、er的管理容器,我们在访问UIView中和绘图、坐标有关属性时,其实是访问了它管理的CALayer的相关属性。,QQ学习群:262779381,5.1.4UIView中的layer属性,QQ学习群:262779381,在使用layer属性之前,我们需要将QuartzCore.framework框架引入到项目中,如果不引入,我们就无法使用layer的相关属性。相信添加框架的过程大家应该掌握,我们这里在讲解一遍。首先在选择当前的项目,然后再选项卡中选择Build Phases,然后选择Link Binary With Libraries选项,最后搜索相应的框架单击“+”按钮进行添加,如图所示。,首
45、先我们可以通过点语法来设置layer的基本属性,比如背景颜色,层的圆角程度等。圆角属性可以通过self.view.layer.cornerRadius属性来设置;还有一点,其实layer属性和UIView视图的用法是很相似的,都是类似树型的结构,就是说多个layer之间也存在父层和子层的概念。下面在我们创建一个视图,然后对视图的layer属性进行操作。 1./创建视图 2. UIView *baseView = UIView allocinitWithFrame:UIScreen mainScreen.applicationFrame; 3. baseView.backgroundColor
46、= UIColor blueColor; 4. self.view addSubview:baseView; 5. /设置视图的layer属性 6. baseView.layer.backgroundColor = UIColor orangeColor.CGColor; 7. baseView.layer.cornerRadius = 20.0f; 8. /创建子layer层 9. CALayer *Mylayer = CALayer layer; 10. Mylayer.frame = CGRectMake(50, 100, 200, 100); 11. Mylayer.backgroun
47、dColor = UIColor redColor.CGColor; 12. Mylayer.cornerRadius = 10.0f; 13. baseView.layer addSublayer:Mylayer;,QQ学习群:262779381,相信上面的代码读者们自行能够理解,我觉得大家可能在设置layer层背景颜色上会有点疑问,为什么在UIColor redColor后面要使用CGColor属性呢?如果将.CGColor去掉会怎样?如果将.CGColor去掉的话,系统会报错误。原因是在对layer层进行操作时,我们需要用到CGColor类,它主要用于CoreGraphics框架之中,C
48、GColor是一个结构体,我们通常在使用CGColor时是使用它的引用类型CGColorRef。 我们利用cornerRadius属性将层的4个角设置成了圆角,然后又在视图的层上面添加了一个子层。是不是和UIView很类似?其实二者还是有一个很重要的不同,就是UIView可以相应用户事件,而CALayer不行。UIView主要是用于对显示内容的管理,而CALayer侧重于对内容的绘制。我们可以来比较UIView和CALayer之间的不同。相同点是二者都拥有树型的结构,都能够显示绘制的内容;不同的是UIView是用来显示内容的,并且可以处理用户事件,而CALayer是用来绘制内容的,还可以实现复
49、杂的动画效果,但是CALayer不能处理用户事件。二者之间关系紧密,UIView是CALayer高层的实现与封装,而CALayer也依赖于UIView提供的容器来显示绘制的内容。,QQ学习群:262779381,我们还可以为子层添加阴影效果,用户可以自行设置阴影的偏移量、颜色、半径等属性。我们在上面代码的基础上为子层设置阴影效果。 1./创建子layer层 2.CALayer *Mylayer = CALayer layer; 3.Mylayer.frame = CGRectMake(50, 100, 200, 100); 4.Mylayer.backgroundColor = UIColor redColor.CGColor; 5.Mylayer.cornerRadius = 10.0f; 6.Mylayer.shadowOffset = CGSizeMake(0, 3);/设置偏移量 7.Mylayer.shadowRadius = 5.0;/设置半径 8.Mylayer.shadowColor =UIColor blackColor.CGColor; 9.Mylayer.shadowOpacity = 0.8;/设置阴影的不透明度 10.baseView.layer addSublayer:Mylayer;,