iOS之UIView
初识iOS APP开发####
在iOS APP开发中, main函数仍是程序的入口和出口, 但main函数不需要程序员手动去实现, 系统已经自动实现。接下来介绍关于main.m文件中的一些知识:
-
首先导入 UIKit/UIKit.h 和 AppDelegate.h
UIKit是系统的一个框架, 里面包含了iOS应用开发中几乎所有的视图控件相关的类和其他的一些常用的类; 也包含了Foundation库; AppDelegate.h遵守UIApplicationDelegate协议的类 -
main函数中调用UIApplicationMain函数
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
1> 第一个和第二个参数: 系统参数2> 第三个参数: 需要传入一个UIApplication的子类, 在UIApplicationMain中会创建这个类的对象, 用来检测应用程序的状态, 用来检测应用程序的状态的改变; 如果传入nil, 那么UIApplicationMain中就会创建一个UIApplication的对象用来检测应用程序状态发生改变后, 通知UIApplication的代理来处理这些事件的改变
3> 第四个参数: 遵守UIApplicationDelegate协议的类, 作用是用来处理应用程序状态发生改变的事件。 UIApplication的对象用来检测应用程序的状态发生改变。NSStringFromClass(类): 讲一个类转换成字符串
iOS应用程序实质是一个死循环, iOS编程的实质就是实现UIApplicationDelegate协议的协议方法
AppDelegate常见的协议方法####
- 方法1: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
- 作用: 这个方法是应用程序启动成功后调用, 可以看做是iOS程序真正的入口, 在这个方法中实现应用程序的所有功能(包括数据下载、数据解析、数据显示)
- 参数1: 当前应用程序对象(委托)
- 参数2: 加载选项
- 方法2: - (void)applicationWillResignActive:(UIApplication *)application;
- 作用: 应用程序将要变成非活跃状态的时候调用这个方法(按home键/来电)
- 在这个方法中一般关闭定时器、暂停游戏、暂停视频播放等
- 方法3: - (void)applicationDidEnterBackground:(UIApplication *)application;
- 作用: 应用程序已经进入后台的时候会调用这个方法
- 方法4: - (void)applicationWillEnterForeground:(UIApplication *)application;
- 作用: 应用程序将要进入前台的时候会调用这个方法(从后台进入应用程序的时候)
- 方法5: - (void)applicationDidBecomeActive:(UIApplication *)application;
- 应用程序已经变成活跃状态的时候调用这个方法(应用程序显示在界面的那一刻)
- 方法6: - (void)applicationWillTerminate:(UIApplication *)application;
- 应用程序将要终止的时候调用这个方法(关闭不再运行)
不让应用程序在后台运行: 设置info.plist文件 添加 Application does not run in background 键, 设置值为YES。
UIWindow和UIView####
UIWindow
UIWindow是一个UNKit; UIWindow继承自UIView, UIView拥有的属性和方法, UIWindow都拥有; 而UIView是iOS中所有视图(控件)直接或者间接的父类。
UIWindow的作用: 一个应用程序至少有一个窗口, iOS应用程序中一般只有一个(一个应用程序想要展示在硬件设备上, 必须有窗口)
- 创建window对象, 设置frame坐标是(0, 0), 大小是自定义
// 应用程序启动后成功调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 如果不在这个方法中创建界面, 那么程序会自动加载main.storyboard来创建见面(自动回去创建UIWindow)
// 1.创建UIWindow对象
_window = [[UIWindow alloc] init];
// 2.设置frame属性(默认: x和y是0, 宽和高是0) - 从UIView继承下来
// 所有视图想要显示在界面上, 必须设置它的位置(坐标-x和y确定)和大小(宽和高确定), 告诉系统当前这个视图是怎么显示
// iOS中, 坐标计算采用iOS坐标系(原点在左上角)
// struct CGRect {
// CGPoint origin;
// CGSize size;
// };
// 使用c语言方式创建结构体变量
// 坐标
CGPoint point = {0, 0};
// 大小
CGSize size = {375, 667};
// frame是由坐标和大小组成的
CGRect rect = {point, size};
[_window setFrame:rect];
// 3.设置背景颜色
_window.backgroundColor = [UIColor lightGrayColor];
// 4.让window成为主窗口并且显示出来
[_window makeKeyAndVisible];
return YES;
}
1. 创建UIWindow对象
2. 设置frame属性(默认: x和y是0, 宽和高是0)
3. 设置背景颜色
4. 让window成为主窗口并且显示出来
- 创建window, 设置frame坐标是(0, 0), 大小是屏幕大小
//创建window, 设置frame坐标是(0, 0), 大小是屏幕大小
// [UIScreen mainScreen]获取当前手机的屏幕
// [UIScreen mainScreen].bounds : bounds的类型是CGRect, x和y值是0, 并且wight和height是屏幕的宽度和屏幕的高度
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIView
UIView是所有视图类直接或者间接的父类, UIView所有的属性和方法其它视图类都拥有.
- UIView的创建
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 1. 创建window, 设置frame坐标是(0, 0), 大小是屏幕大小
// [UIScreen mainScreen]获取当前手机的屏幕
// [UIScreen mainScreen].bounds : bounds的类型是CGRect, x和y值是0, 并且wight和height是屏幕的宽度和屏幕的高度
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 2.设置背景颜色
self.window.backgroundColor = [UIColor lightTextColor];
// 在这儿来创建界面
// =========== UIView ============
// 创建一个UIView对象
UIView *view1 = [[UIView alloc] init];
// (2) frame属性
// 视图想要显示在界面上, 必须设置frame属性告诉系统显示的坐标和大小
// frame属性中的坐标是相对坐标, 将当前视图添加到哪个视图上, 那么这个坐标就是相对于谁的
// OC中所有的结构体都对应一个make方法, 来快速的创建结构体变量
[view1 setFrame:CGRectMake(100, 100, 175, 102)];
// (3)设置背景颜色
// clearColor 透明
// 通过类方法创建颜色
view1.backgroundColor = [UIColor whiteColor];
// 设置tag值
[view1 setTag:20];
// (4)将视图对象添加到指定的视图上
// 将一个视图添加到另外一个视图上
[_window addSubview:view1];
// ============ 第二个UIView ===========
// (1)创建一个UIView对象, 并且设置其frame
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 50, 50)];
// (2)设置背景颜色
view2.backgroundColor = [UIColor blackColor];
// (3)将视图对象添加到另外一个视图上
// window就是view2的父视图, view2就是window的子视图
[_window addSubview:view2];
// [view1 addSubview:view2];
// (4)设置tag值(如果不设置, 默认都是0)
// 作用:父视图可以通过tag值获取到指定的值
[view2 setTag:10];
// 3.设置为主窗口, 并且显示
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 1.通过tag值去获取当前视图上的子视图
UIView *view = [self.window viewWithTag:10];
view.backgroundColor = [UIColor greenColor];
// 2.获取当前视图上所有的子视图
NSArray *viewArray = [_window subviews];
NSLog(@"%@", viewArray);
// 遍历数组中所有的视图
for (UIView *view2 in viewArray) {
if (view2.tag == 20) {
view2.backgroundColor = [UIColor purpleColor];
}
else if (view2.tag == 10){
view2.backgroundColor = [UIColor cyanColor];
}
}
}
UIView坐标相关属性及方法####
// 创建视图对象
UIView * view1 = [[UIView alloc] init];
// 显示在界面上
[self.window addSubview:view1];
// 设置背景颜色
view1.backgroundColor = [UIColor lightGrayColor];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
view2.backgroundColor = [UIColor blackColor];
[view1 addSubview:view2];
-
1> frame
- 每个想要显示在界面上的控件都需要通过frame属性来确定坐标和大小
view1.frame = CGRectMake(10, 30, 100, 100);
- 每个想要显示在界面上的控件都需要通过frame属性来确定坐标和大小
-
2> center
-
center是当前view视图的中心点的坐标, 确定了视图的frame,视图的center就会被确定
设置视图的中心点, 视图的frame也会随着中心点的变化而变化
CGPoint center = view1.center; NSLog(@"center:%@", NSStringFromCGPoint(center)); // center:(100,100) // 设置中心点, 会改变frame的坐标 view1.center = CGPointMake(200, 200); // center:(200,200)
-
-
3> bounds
- 视图一旦确定了frame, 就确定了bounds的值, bounds的坐标是(0,0), 大小是frame的size
CGRect rect = view1.bounds;
// (0,0,100,100) - 改变bounds的坐标不会影响视图的frame的坐标; 但是会影响当前这个子视图坐标原点(一般不会去设置bounds的值, 只是通过bounds快速获取坐标是(0,0)大小是当前视图大小的frame值)
view1.bounds = CGRectMake(10, 10, 100, 100);
// view1视图不变 - 改变bounds的size会影响frame的size, 也会影响frame的坐标, 但是视图的中心点不会变
view1.bounds = CGRectMake(0, 0, 200, 200);
// (200,200)
- 视图一旦确定了frame, 就确定了bounds的值, bounds的坐标是(0,0), 大小是frame的size
-
4> 形变
旋转、缩放、平移都是对视图的同一个属性进行设置, 后设置的属性会覆盖之前设置的属性
- 旋转(当前视图的子视图也会跟着一起旋转)
// 参数: 角度(pi对应的角度)
[view1 setTransform:CGAffineTransformMakeRotation(M_PI_2)]; - 缩放(当前视图的子视图也会跟着缩放)
// 参数1: x方向的缩放比例
// 参数2: y方向的缩放比例
[view1 setTransform:CGAffineTransformMakeScale(0.5, 0.4)]; - 平移
// 参数1: 在x方向平移单位(+右移 -左移)
// 参数2: 在y方向平移单位(+下移 -上移)
[view1 setTransform:CGAffineTransformMakeTranslation(0, 0)];
- 旋转(当前视图的子视图也会跟着一起旋转)
-
旋转小动画
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_window.backgroundColor = [UIColor whiteColor];
// 创建视图对象
UIView * view1 = [[UIView alloc] init];
// 显示在界面上
[self.window addSubview:view1];
// 设置背景颜色
view1.backgroundColor = [UIColor lightGrayColor];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
view2.backgroundColor = [UIColor blackColor];
[view1 addSubview:view2];
view1.tag = 10;
// 添加一个定时器
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(yhTransform) userInfo:nil repeats:YES];
[view1 setTransform:CGAffineTransformMakeRotation(0)];
[_window makeKeyAndVisible];
return YES;
}
- (void) yhTransform {
// 获取旋转的视图
UIView *view = [_window viewWithTag:10];
// ================== 时时旋转 ===============
// 使用静态变量存储上一次结束的时候视图的旋转的角度
static CGFloat angle = M_PI/8;
// 每0.1秒让视图的旋转角度增加pi/10
[view setTransform:CGAffineTransformMakeRotation(angle)];
// 保存当前的旋转角度
angle = angle + M_PI/8;
}
- 自由缩放小动画
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_window.backgroundColor = [UIColor whiteColor];
// 创建视图对象
UIView * view1 = [[UIView alloc] init];
// 显示在界面上
[self.window addSubview:view1];
// 设置背景颜色
view1.backgroundColor = [UIColor lightGrayColor];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
view2.backgroundColor = [UIColor blackColor];
[view1 addSubview:view2];
view1.tag = 10;
// 添加一个定时器
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(yhTransform) userInfo:nil repeats:YES];
[view1 setTransform:CGAffineTransformMakeRotation(0)];
[_window makeKeyAndVisible];
return YES;
}
- (void) yhTransform {
// 获取旋转的视图
UIView *view = [_window viewWithTag:10];
// 随机缩放比例
NSInteger arc = arc4random() % 100 + 1;
CGFloat prop = arc / 50.0;
[view setTransform:CGAffineTransformMakeScale(prop, prop)];
}
- 时时平移小动画
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_window.backgroundColor = [UIColor whiteColor];
// 创建视图对象
UIView * view1 = [[UIView alloc] init];
// 显示在界面上
[self.window addSubview:view1];
// 设置背景颜色
view1.backgroundColor = [UIColor lightGrayColor];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
view2.backgroundColor = [UIColor blackColor];
[view1 addSubview:view2];
view1.tag = 10;
// 添加一个定时器
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(yhTransform) userInfo:nil repeats:YES];
[view1 setTransform:CGAffineTransformMakeRotation(0)];
[_window makeKeyAndVisible];
return YES;
}
- (void) yhTransform {
// 获取旋转的视图
UIView *view = [_window viewWithTag:10];
static float translation = 0;
static float translationValue = 1;
[view setTransform:CGAffineTransformMakeTranslation(translation + 5 * translationValue, 0)];
// 跟新平移距离
translation += 5*translationValue;
if (view.frame.origin.x <= 0) {
translationValue = 1;
}
if (view.frame.origin.x >= _window.frame.size.width - view.frame.size.width)
{
translationValue = -1;
}
}
父子视图关系的属性和方法####
一个视图只能有一个父视图; 一个视图可以有多个子视图; 一个视图被多次添加到其他视图上, 最后一次添加有效
- 获取一个视图的父视图
UIView * greenSuper = [greenView superview]; - 获取视图上得所有子视图
NSArray * array = _window.subviews;
>注意: 有时会获取到一些意料之外的视图
- 获取window
前提: 获取window的时候, 已经显示出来
应用程序中, 程序启动后界面上所有的视图都是直接或者间接的添加到window, 所以可以通过界面上所有的视图拿到当前应用的window
UIView * window = [redView window]; - 将视图从父视图上移除
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(300, 400, 60, 40)];
button.backgroundColor = [UIColor blackColor];
[button addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchDragInside];
[self.window addSubview:button];
[greenView removeFromSuperview];// 移除
>一旦视图从父视图上移除, 那么父视图就不能通过viewWithTag:和subViews来获取当前的视图
>已经从父视图上移除的视图, 在内存中还是存在的; 移除只是不让这个视图显示在父视图上而已
同父视图的子视图的层次关系####
如果多个视图添加到同一个父视图上, 公共部分后添加的会覆盖先添加的
// 创建红色视图
UIView * redView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
redView.backgroundColor = [UIColor redColor];
redView.tag = 10;
[_window addSubview:redView];
// 创建黄色视图
UIView * yellowView = [[UIView alloc] initWithFrame:CGRectMake(80, 80, 100, 100)];
yellowView.backgroundColor = [UIColor yellowColor];
yellowView.tag = 20;
[self.window addSubview:yellowView];
// 创建绿色视图
UIView * greenView = [[UIView alloc] initWithFrame:CGRectMake(110, 110, 100, 100)];
greenView.backgroundColor = [UIColor greenColor];
greenView.tag = 30;
[_window addSubview:greenView];
- 将一个视图的层次设置成最上面
[_window bringSubviewToFront:redView]; - 将一个视图的层次设置成最下面
[_window sendSubviewToBack:yellowView]; - 插入视图(如果被插入的视图已经显示在界面上, 那么通过插入方法只是改变它的层次关系; 如果被插入的视图没有添加到界面上, 通过插入方法可以将视图添加到界面上, 并且改变层次关系)
- 将某个视图插入到指定的视图上面
[_window insertSubview:greenView aboveSubview:redView]; - 将某个视图插入到指定的视图下面
[_window insertSubview:greenView belowSubview:yellowView];
- 将某个视图插入到指定的视图上面
层次与事件接收####
- 父视图不能接收事件, 则子视图无法接收事件
如果本来可以接收事件的视图, 添加到了不能接收事件的视图上, 那么本来可以接收事件的视图也接收不到事件了
- 子视图超出父视图的部分, 不能接收事件
- 同一个父视图下, 最上面的视图, 首先遭遇事件, 如果能够接收, 就不向下传递事件。 如果不能接收, 事件向下传递。
- 设置控件是否可以接收事件
imageView.userInteractionEnabled = YES;
不能接收事件: 感受不到手指的触摸
能接收事件: 能感受到手指的触摸
并不是能够接收事件就可以响应事件, 但是能响应事件的前提是能接收事件
默认情况下: UIWindow、UIView和UIButton等可以接收事件, UILabel和UIImageView等不可以接收事件
UIView动画####
上面提到一种动画方式, 通过形变(旋转、缩放、平移)对当前的视图进行时时的更改, 达到动画效果, 但是在很多时候, 通过UIView的形变产生的动画并不能满足动画的要求, 但是UIView还有一种动画效果, 可以动态的改变视图的frame、形变、颜色、透明度, 实现动画
- 第一种: + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;
- 功能: 动态的改变视图的frame、形变、颜色、透明度
- 参数1: 动画时间(单位/s)
- 参数2: block, 用来实现动画结果的代码段
[UIView animateWithDuration:3 animations:^{
// 使用动画效果改变视图的frame
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y + 400, 200, 200);
// 使用动画效果改变视图的背景颜色
view.backgroundColor = [UIColor greenColor];
// 使用动画效果改变视图的透明度
// 改变父视图的透明度, 子视图的透明度会跟着改变; 如果只想改变父视图的透明度, 就改变父视图背景颜色的透明度
view.alpha = 0.3;
// view.backgroundColor = [UIColor colorWithRed:123/255.0 green:231/255.0 blue:145/255.0 alpha:0.3];
// 使用动画效果改变视图的形变
view.transform = CGAffineTransformMakeScale(0.5, 0.5);
}];
- 第二种: + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
- 功能: 动态的改变视图的frame、形变、颜色、透明度
- 参数1: 动画时间(单位/s)
- 参数2: block, 用来实现动画的结果的代码段
- 参数3: block, 动画结束后需要执行的代码段
[UIView animateWithDuration:2 animations:^{
// 动画结果
view.transform = CGAffineTransformMakeScale(0.5, 0.5);
} completion:^(BOOL finished) {
// 动画结束后移除
//[view removeFromSuperview];
}];
- 第一种与第二种动画进行嵌套使用
[UIView animateWithDuration:2 animations:^{
// 缩小一倍
view.transform = CGAffineTransformMakeScale(0.5, 0.5);
} completion:^(BOOL finished) {
// 变小后的动画, 再变回去
[UIView animateWithDuration:2 animations:^{
// 动画结果
view.transform = CGAffineTransformMakeScale(1, 1);
}];
}];