UI层复习笔记
在main文件中,UIApplicationMain函数一共做了三件事
- 根据第三个参数创建了一个应用程序对象
- 默认写nil,即创建的是UIApplication类型的对象,此对象看成是整个应用程序的一个抽象,负责存储应用程序的状态。
- 根据第四个参数创建了一个应用程序代理类对象
- 所谓代理,及帮助另一个对象做事情。上面第一步中创建的应用程序对象只负责存储应用程序的状态,但不提供响应,而是给代理发消息,由代理负责针对不同的状态提供响应。比如说:程序一启动,代理就要响应一下,说明弹出的第一个界面是谁。
- 其中,就是传入一个类的类名字符串即可,此代理类对象一定是系统创建的,而且只有一个,也就是单利。其中AppDelegate class返回的是这个类的类型描述信息,在使用NSStrinFromClass这个函数,从类型信息中把类名以名字符串形式返回。
- 第三件事,启动了事件循环
- 一个背后运行的死循环,用于不停地检测屏幕上的触点事件,一检测到触摸事件,立即将此事件传给用用程序,让程序提供相应
如何搭建一个界面? - UIViewController
- 作用:
- 负责创建界面
- 负责提供界面与用户的交互响应
- 特点:
- 天生自带一个视图属性,所有界面设计就是添加到这个视图即可。
- 规范写法:
- step1:创建一个类,继承自UIViewController
- step2:在类中的viewDidLoad方法方法中,编写构建界面的代码
- step3:在启动方法中,只需要将这个自定义的类创建出实例,作为window的根视图控制器即可
- viewDidLoad方法的特点:
- 此方法是控制器的那个view生命周期的起始点,即创建完view实例之后,第一个执行的方法,并且此方法只会调用一次
- 除此方法外,view还会存在其他状态,如:viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear,这些方法会随着view的显示或隐藏而执行多次,但只要控制器没有销毁,view没有销毁过,则viewDidLoad方法只会调用一次
界面元素的基础 - UIView
- 是什么?所有界面上看的见的东西都是UIView的子类,系统定义的一个通用的描述界面上某个可显示的矩形区域,一个重要的特性就是具备容器性,即UIView可以内部添加其它的UIView,除此以外它还能提供触点的响应。
- 核心属性:
- frame(框架,边框):用于描述这个视图在父视图中的位置及占据的区域大小
- CGRect结构提类型
- 包含origin属性和size属性
- origin:CGPoint类型的结构体
- size:CGSize类型的结构体
- CGRect包含四个浮点,两个存储x和y用于定位,两个存储width和height用于描述大小
- CGRect结构提类型
- 如何构建一个CGRect类型的结构体变量呢?
- 使用一组函数即可,函数名规律是是:结构体类型名 + Make
CGRect -> CGRectMake(x,y,w,h);
CGPoint -> CGPointMake(x,y);
CGSize -> CGSizeMake(w,h);
UIEdgeInset -> UIEdgeInsetMake();
特殊:UIRange -> UIMakeRange()
- 使用一组函数即可,函数名规律是是:结构体类型名 + Make
- frame(框架,边框):用于描述这个视图在父视图中的位置及占据的区域大小
- 有哪些子类?
- UIWindow、UILabel都是UIView的直接子类,有一个特殊的分支叫UIControl,特殊之处在于有自己的高级事件,也管这个分支叫控件,UIButton、UITextField都是控件,但UILabel不是空间,虽然口头交流时经常误把很多不是空间的视图也称之为控件,但概念要清楚,只有UIControl的子类才能叫做控件。
UIView的几个子类:
-
UILabel 标签
- 作用:显示文字
- 核心属性:
text
: 类型NSStringnumberOflines
:显示的行数,默认是1,如果设置为0,则代表行数无上限font
:字体,字号textColor
:文字颜色backgroundColor
:背景色textAlignment
:水平方向文本的对齐方式
-
UIButton 按钮
- 作用:以文字或图片的样式提供给用户一个可点击并相应的区域
- 核心属性:默认图文左右排
- 文字title:
setTitle: forState:
- 图片image:
setImage: forState
对于后缀是.png的图片省略后缀,其他的图片类型就需要加后缀名。 - 背景图backgroundImage:
setBackgroundImage: forState
- 按钮有四个状态:normal(摆在那不动)、highlight(高亮状态,按下去不松手)、selected(选中状态,通过设置按钮的selected属性为YES才会进入到这个状态)、disable状态(不能用状态,通过设置按钮的enable属性为NO时进入此状态)
- 文字title:
- 创建事项:
- 使用工厂方法创建按钮式,可以通过参数指定是系统版还是自定义版
- 使用new或alloc init 方式创建的按钮,等价于传自定义版参数
- 如何选择使用系统版,还是自定义版按钮呢?
- 因为系统自带高亮,所有美工给一套图时,就选系统版
- 如果美工给了两套图,就选择则自定义版
- 自定义扮,title的文字颜色为白色,系统板时有默认颜色,title为蓝色
- 核心事件:
- 事件种类:
touchUpInside
- 如何添加对事件的响应:
addTarget: action: forControlEvent
- 事件种类:
-
UITextField
- 作用:接受输入
- 核心属性:
text属性:NSString类型。可读可写,读取就是获取输入的文字,给属性赋值,则文字会显示到文本框中
键盘属性
设置边框样式:borderStyle
设置键盘样式:keyboardType
设置键盘右下角按键的样式:returnType
设置键盘整体色系风格:keyboardAppearance
设置键盘是否是密码框:secureTextEnter
- 核心事件:
插播知识点
[xxx copy]
将长度可变的的复制成长度不可变的[xxx mutableCopy]
将长度不可变的复制成长度可变的NSArray --> [NSArray NSmutableCopy] -->NSmutableArray
问题
字符串类型的属性是用什么修饰?
答案:使用copy修饰,因为有一种特殊情况,就是一旦将MutableString赋值给属性,一旦有其他的引用也指向这个可变字符串,就会有修改其内容的可能。这样的话,就会导致明明声明的是不可变长度的属性,会发生内容的改变。一旦用了copy修饰,则就算赋值一个可变长度的内容,也会先执行一次copy,将其拷贝成一份长度不可变的副本,让属性只想这个副本,就算有其他引用修改那个长度可变的字符串,也不会影响副本的内容。
-
文本框
- 键盘为什么弹起来?
- 当有触点在文本框时,系统对这个触摸动作进行了响应,相应的结果就是让文本框成为第一响应者
-
[textField becomeFirstResponder
成为第一响应者 ,调用键盘
- 如何收键盘?
- 取消掉文本框的第一响应者身份即可
[textField resignFirstResponder]
- 什么时候收键盘?
-
情况一:点击屏幕的空白处:点击控制器的那个view
- 实现控制器的
touchesBegan:
方法即可
- 实现控制器的
- 如果有多个键盘:如果界面中有多个文本框,那么可以通过结束他们父视图的编辑状态方法
- 批量关闭所有文本框弹起的键盘:
[self.view endEditing:YES];
- 批量关闭所有文本框弹起的键盘:
-
情况二: 点击键盘右下角return按键
- (BOOL)textFieldShouldReturn:(UITextField *)textField
- 右下角按键类型:
returnKeyType
-
情况一:点击屏幕的空白处:点击控制器的那个view
- 密码框:
secure
- 提示性:
placeHolder
- 键盘为什么弹起来?
-
代理
- 遵守协议
- 实现协议中的方法
- 设置委托方的代理人为当前对象
- 代理方法的第一个参数,是委托方本身。
-
懒加载
- 也叫延迟加载,等到需要使用时才开辟空间创建对象
-
消息框UIAlertContent
- 作用:弹出提示,有两种样式,屏幕中间,屏幕底部
- 如何解决样式?创建实例的时候,通过style参数,alert样式在屏幕中间,actionsheet在屏幕底部
-
addTextFieldWithConfigurationHandler:
参数是 block ,在block中可以设置 alert帮我们创建 文本框 - 数组中的 文本框 是 第四步 添加进来的文本框
UITextField *usernameField = alert.textFields[0];
UITextField *passwordField = alert.textFields[1];
-
使用xib技术实现界面
- 理念:将控制器中原本需要些大量代码进行构建界面的过程,通过一个后缀是xib的文件简化此操作。当再去创建控制器实例时,系统会通过读取xib文件,完成界面的创建。针对系统创建的这个视图,需要在控制器中访问时,可以通过连线的方式完成关联。
- IBOutlet关键字:将控制器中的属性与界面中系统创建的某个视图关联在一起
- IBAction关键字:键控制器中的方法与界面中系统创建的某个视图的时间关联在一起
-
切换VC
- A -> B:使用的是A控制器的presentViewController方法
- B -> A:使用的是B控制器的dismissViewController方法
-
注意A和B的声明周期
:A推出B时,虽然看不见A了,但是A没有被摧毁,从B返回A时,B会被销毁,A从隐藏状态编程显示状态
-
使用xib简化创建界面的过程
- 如何实现
- 借助于系统的Interface Builder 完成,IB以前是一款独立的软件,现在整合到xcode中, 只需要创建自定义的控制器时,勾选下面的“Also Creat Xib file”选项,则自动生成与控制器名相同,后缀为xib的文件,xib以前叫做叫nib
-
UIStepper 步进控件
- 作用:记录一个浮点值,并且控件提供了两个按键界面,由用户精确地控制记录支个值得递增或递减
- 核心属性:
value
- 核心事件:
valueChanged
-
UISlider 滑块控件
- 作用:记录一个浮点值,通过一个可以滑动的按键,快速在某个范围内得到一个不容易精确控制的数值
- 核心属性:
value
- 核心事件:
valueChanged
-
UISwitch 开关控件
- 作用:记录一个布尔值,通过点击的方式,可以记录用户是否的选择
- 核心属性:
on(BOOL类型)
- 核心事件:
valueChanged
-
SegmentedControl 分段控件
- 核心属性:
selectedSegmentIndex
- 核心事件:
valueChanged
- 核心属性:
-
Activity Indicator 菊花控件
- 核心属性:
isAnimating
- 核心方法:
startAnimating
stopAnimating
- 核心属性:
-
Progress 进度提示条
- 核心属性:
progress
(0 ~ 1 浮点)
- 核心属性:
注意:浮点型和整形相比,永远也到不了1。浮点型精确到小数点后6位
-
NSTimer定时器
- 作用:可以设置某方法,每个一段时间,自动执行
- 如何创建并启动?
- timerXXXXX : 创建好的定时器,不会自动启动,我们只有把该定时器添加到事件循环中
- scheduleXXXX: 创建好定时器后,自动启动
-
DatePicker
- 核心属性:
date
- 核心方法:日期格式化
HH - mm - ss yyyy - MM - dd
- 核心属性:
-
PickView
- 我们关注三问一答
- 三问:(DataSource)
- 有多少列
- 每列有多少行
- 每行长什么样子
- 一答:(delegate)
- 选中某行如何处理
- 三问:(DataSource)
- 我们关注三问一答
-
UINavigationController导航控制器
- 作用:为了管理多个控制器
- 配置导航类(NavigationBar)
- 高度:算上状态栏64个点(状态栏20个点)
- 内容:通过navigationItem属性来完成设置
navigationItem设置的是每个界面上导航栏中的内容
- 左:
leftBarButtonItem
/leftBarButtonItems
- 中:
title
/title View
- 右:
rightBarButtonItem
/rightBarButtonItems
- 左右都是类似于可点击的按键,是UIBarButtonItem类型
- 如果修改
NavigationBar
的外观,该导航下所有子控制器都会改变self.navigationController.navigationBar.tintColor = [UIColor redColor];
- 配置工具栏(toolBar)
- 位于导航界面的底部,默认是隐藏的,高度44个点,通过设置
Navigation.toolBarHidden = NO
即可显示 - toolBar中可以通过toolBarItem的属性,设置按键,位置不分左中右,可以用木棍,弹簧调整视图。
- 位于导航界面的底部,默认是隐藏的,高度44个点,通过设置
- 设置导航控制器的titleColor
-
UIImageView
- UIImage(存图片) -> UIImageView(显示图片的视图)
- 核心:image
UIViewContentModeScaleToFill 默认,设置的宽高是多少,就是多少
UIViewContentModeScaleAspectFit 保持宽高比
UIViewContentModeScaleAspectFill 保证宽高比,可能图片会被切割掉
- //裁剪 姿势图超出的部分
iV.clipsToBounds = YES;
-
UIKit层面动画
- 预备:动画 -- 序列帧动画
- 每一帧是一张静态的图片,按照一定间隔时间,快速连续播放,最终通过人眼的视觉停留效果实现的动画
- 预备:动画 -- 序列帧动画
-
UIScrollView滚动视图
作用:用于查看更大范围的图片或文字内容信息的视图
特点:虽然是视图,但本身scrollView没有外观,主要是通过加载子视图来完成的展示,内部子视图的区域可以大于scrollView占据的空间,通过滑动这种交互方式能够实现查看超出范围的那些子视图
-
核心属性:
frame
可视区域的大小contentSize
内容大小(可以滑动区域的大小)contentOffset
记录滑动的偏移量pagingEnabled
设置整页滑动showsHorizontalScrollIndicator
是否隐藏水平滚动条showsVerticalScrollIndicator
是否隐藏竖直滚动条bounces
是否有弹性效果
-
UIPageControl
- 作用:页数的提醒
- 外观:一条区域中包含多个小圆点
- 核心属性:
-
numberOfPages
圆点的个数 -
currentPage
当前被选中的是第几个小圆点(下标从0开始) -
pageIndicatorTintColor
设置未选中的圆点颜色 -
currentPageIndicatorTintColor
选中圆点的颜色 -
userInteractionEnabled
是否与用户交互
-
- 与ScrollView配合页数移动方法:
- 在scrollView的协议方法中
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSInteger currentPage = scrollView.contentOffset.x / scrollView.frame.size.width + 0.5;
self.pageControl.currentPage = currentPage;
}
-
UITableView表示图
- 作用:实现以一列多行来显示大量数据的一种视图,父类是ScrollView
- 表格样式
- 普通样式:
plain
- 分区样式:
group
- 普通样式:
- 表示图的样式
- 表示图的使用
- 创建实例
- 设置frame
- 添加到父视图中
- 设置数据源方法 三问
- 设置代理 一答
-
UITableViewController表示图控制器
- 特点:
- 继承自UIViewController,天生自带一个UITableVIew属性,通过tableView属性访问即可,此表示图的dataSource和delegate代理已经被设置为当前的表示图控制器,并且表示图控制器也已经遵守了UITableView和UITableViewDelegate协议
- 使用:
- 在使用上,在创建一个类继承UITableViewController,只需关注三问一答即可
- 特点:
-
cell的复用
- 方式一:
- 原理:系统会自动将那些超出屏幕,看不见的对象回收到tableView的一个空闲队列中存储,所有在回答第三问,需要一个cell对象时,看有没有已经回收的,可以拿出来使用的cell对象,如果没有取到可重用的cell,我们就创建一个,如果取到了可重用的cell,我们就使用cell对象,但是要重新设置cell的显示内容
- 方式二:
- 原理:系统会自动将那些超出屏幕,看不见的对象回收到tableView的一个空闲队列中存储,所有在回答第三问,需要一个cell对象时,看有没有已经回收的,可以拿出来使用的cell对象,如果没有取到可重用的cell,系统会按照我们之前注册的cell帮我们创建一个cell,如果取到了可重用的cell,我们就使用cell对象,但是要重新设置cell的显示内容
- UITableViewCell的组成:
- 内容视图:
系统版:已经提供了三个可用的空间,用于显示文字或图片,可以通过cell的属性进行设置
cell.textLabel
cell.detailTextLabel
cell.imageView
-
样式有四款系统版:
- UITableViewCellStyleDefault
- UITableViewCellStyleValue1
如果没有图片 - UITableViewCellStyleValue
- UITableViewCellStyleSubtitle
- UITableViewCellStyleDefault
-
自定义内容视图:
- 自定义内容驶入需要通过单元格的contentView属性,找到contentView,然后往其上面添加自己的视图
cell.contentView addSubview:
视图 - 系统版:通过cell.accessoryType属性设置
- 四款:
- 自定义版
- 给cell的accessoryView复制一个自己创建的视图
cell.accessoryView = 自定义视图
- 自定义内容驶入需要通过单元格的contentView属性,找到contentView,然后往其上面添加自己的视图
- 内容视图:
- 方式一:
表格结合各种数据模型的显示
-
step1:一定要为表示图控制器增加一个属性,存储表格要显示的数据,基本上类型定为数组类型
- 前提:表格的行数是不定的,也叫动态表格
- 将数组显示到表格中:NSArray -> TableView
- 将对象数组显示到表格中
- 自定义一个数据模型类 Model(M)
self.tableView.tableFooterView
:在viewDidLoad中直接设置表尾视图self.tableView.tableHeaderView
:在viewDidLoad中直接设置表头视图self.tableView.rowHeight
:设置行高 都设置行高heightForRowAtIndexPath:
:设置行高的代理方法-
向表格中添加数据
- 方式一: 全部刷新
reloadData
- 方式二: 局部刷新
-
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataArr.count - 1 inSection:0];
在使用前,一定要先将插入的数据插入到数组 [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
-
- 方式一: 全部刷新
委托反向传值增加数据
代理传值
-
表格的编辑模式
- 什么是表格的编辑?
- 表格上提供了删除,增加,移动这样的标识,点击后可以实现表格中的数据删除,增加以及移动
-
如何进入到表格的编辑状态
- 设置表格的
editing
为YES即可
- 设置表格的
-
如何增加或删除®
- 两问一答
- 问一:当前行是否可以编辑(选问,默认是所有都能编辑)
canEditRowAtIndexPath:
- 问二:当前行是如何编辑<增加,删除>(选问,默认都是删除)
editingStyleForRowAtIndexPath:
- 答一:增加或删除编辑按键点中时应该如何处理
commitEditingStyle: forRowAtIndexPath:
-
如何移动表格中的单元格
- 一问一答
- 一问:当前行是都可以移动
- 一答:移动动作完成后如何处理后续工作
performSelector: withObject: afterDelay: 延迟多久调用什么方法
-
静态表格 行数固定不变
- 主要应用场景:设置界面
- 实现特点:控制器中会出现大量的硬编码,会有很多的if switch 这样的分支语句
下拉刷新 UIRefreshControl 的实例进行下拉刷新
-
UICollectionView集合视图
- 视图可以一多行多列的形式来展示数据,是从tableView演变而来,所以在使用上,与tableView很想,从iOS6以后开始支持
- 与tableView的异同点
-
相同点:
- UITableView 关注三问一答(几个分区,每个分区多少行,每行什么样子)
- UICollectionView 关注三问一答(几个分区,每个分区多少项,每项什么样子)
-
不同点:
- UITableView
- 默认自带了用于显示数据的三个视图 textLabel,detailTextLabel,imageView
- 布局:系统定义好,永远是一列多行,从上到下,按顺序依次排列
- UICollectionView
- 不带有任何系统定义好的用于显示数据的视图,只能访问以下几个属性
-
backGroundColor
,backGroundView
,contentView
-
- 布局:需要搭配一个独立的对象来对视图中的多各项进行布局
- 布局对象:所属类型为UICollectionViewLayout或其子类,系统只给我们提供一种布局,UICollectionViewFlowLayout(流式布局)继承自UICollectionViewLayout
- 不带有任何系统定义好的用于显示数据的视图,只能访问以下几个属性
- UITableView
-
UITabBarController选项卡控制器
- 以横向并列卡片式,来管理多个控制器,并已经实现了点击后的切换,和UINavigationController很想都是管理子控制器的,但不同的是导航控制器是层层推进的
tabBarController.viewControllers = @[avc,bvc,cNavi];
设置当前是第几页:tabBarController.selectedIndex = 1;
BViewController *bVC = tabBarController.viewControllers[1];
bVC 传值;
self.tabBarController.tabBar.tintColor = [UIColor purpleColor];
self.tabBarItem.image = [[UIImage imageNamed:@"line_bell"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
一个永远不受tintColor影响的图片
故事版
特点:快速开发,并可以在故事版文件了解整个应用程序的界面结构
-
启动时,系统自动做了什么?
- 根据target中配置加载Main.stroyboard文件
- 自动创建window对象
- 自动创建在故事版中有启动箭头指向的那个界面背后控制器对象
- 自动将控制器对象设置为window的rootViewController
- 自动将window显示出来
-
跳转
- 连线跳转:从一个触发跳转的控件或场景(故事版看得见界面)连线到要跳转到的目标控制器
- 连线:segue 每条线都是一个对象
-
明确跳转源头
- 明确知道跳转是哪个控件触发的,实现方式,无需写代码,直接连线
-
不明确跳转源头:
- 场景中触发跳转的控件可能是使用代码创建的,场景中条船到下一个场景的控件不明确,这些情况都是不明确跳转源头的,实现跳转的方式,选中源场景中的小黄点,连线到目标场景,选中自动生成的线,在第四个检查器中,identifier属性,为这根线起一个标识,最后在代码中,通过控制器调用
performSegueWithIdentifier
+ 线的标识,完成触发这一次跳转动作
- 场景中触发跳转的控件可能是使用代码创建的,场景中条船到下一个场景的控件不明确,这些情况都是不明确跳转源头的,实现跳转的方式,选中源场景中的小黄点,连线到目标场景,选中自动生成的线,在第四个检查器中,identifier属性,为这根线起一个标识,最后在代码中,通过控制器调用
-
跳转到故事版中一个独立的场景
- 先给独立的创景在第三个检查器中,设置storyboardID
在想要跳转时利用故事版的instantiateViewControllerWithIdentifier
方法根据storyboardID创建对应的控制器对象
- 先给独立的创景在第三个检查器中,设置storyboardID
-
使用present或push跳转即可
- 跳转其他xib的控制器
- 跳转到其他故事版的场景中
-
传值
prepareForSegue:
使用这个方法跳转时,需要拦截下来segue对象,
找到segue对象的目标控制器segue.destinationViewController
如果目标控制器是一个导航控制器,还需要使用navi.viewControllers[0]
找到目标控制器下的跟控制器
如果当前控制器有两条先,需要进行判断-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navi = segue.destinationViewController;
RegisterViewController *registerVC = navi.viewControllers[0];
registerVC.delegate = self;
}
- viewController的属性,隐藏控制器中所有Bar:
hideBottomBaronPush
- 9 切片
- 目的:改图,使用代码的方法或直接使用xcode的功能,对一些有规律的 或 内容重复的图片进行动态的修改大小
-
通过代码实现9切片
-
image = [image stretchableImageWithLeftCapWidth:30 topCapHeight:30];
:这个是拉伸处理 -
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 20, 20, 20)];
:默认是磁块平铺 image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(20, 20, 20, 20) resizingMode:UIImageResizingModeTile];
-
返回值都是返回一个图片,需要用一个新的图片来接受
第二部分
绘图:(绘制图片 绘制字符串 绘制图形)
变形:(位移 旋转 缩放)
UITouch
手势:(点击 双击 轻扫 拖拽 长按 捏合 旋转)
深入坐标系(frame bounds center transform)
动画:核心动画 CoreAnimation (CA动画)
布局:(代码 AutoResing AutoLayout SizeClasses)
通知
聊天页面练习
绘图:
基本概念:
图像和显示器.显示器如何显示内容?
由晶体组成->发RGB的光,混合后产生不同的颜色
整个显示器显示的就是一副好多个彩色的点构成的图像
一个点对应就是一个像素,用4个字节保存,系统会自动将临近的4个点使用一个平均色来记录,于是图像的大小就变成了原来的1/4-
图像
内存中的图像有2种:- 位图(点阵图)用RGB来生成(PNG,JPG)
- PNG 带透明通道,iOS开发尽量使用PNG,IPG会自动渲染回PNG
- 矢量图,保存的不是点,记录的是生成图像的公式及函数,放大,缩小时不会失真(多用于广告,海报)
- 位图(点阵图)用RGB来生成(PNG,JPG)
-
如和绘图
- OC对象与图形的转换
- Core Graphics(核心绘图) 一套C语言的函数库
- 另外一个名字:Quart2D 苹果设备(iOS.OSX)上的2D的绘图引擎
- 为了使用方便,系统对CoreGraphice做了一些封装,直接使用UIKit下面的UIImage UIColor NSString UIBezierPath 类型也可以实现简单的曲线
- OC对象与图形的转换
UITouch触摸
什么是触摸:是一个UITouch类型的对象,当用户touch视图时,会自动将触碰物理性的动作,转换成对象存储起来,这个对象就是UITouch对象
-
如何获取touch对象
- 情况一:自定义视图类,重写类中指定方法,在这个方法中,通过传入的参数可以获得touch对象
- 情况二:对于触碰控制器自带的View,在控制器中重写指定方法,通过参数也可以获得touch对象
-
touchBegan
touchMove
touchesEnded
手势
将用户物理性的触屏操作转变成了对象存储起来,所有手势的父类UIGestureRecognizer
-
系统将一些有特点的触屏操作封装了不同的手势类型,包括以下几种:
-
UITapGestureRecognizer
点击 -
UISwipeGestureRecognizer
清扫 -
UILongPressGestureRecognizer
长按 -
UIPanPressGestureRecognizer
拖拽 -
UIPinchPressGestureRecognizer
捏合 -
UIRotationPressGestureRecognizer
旋转
-
-
如何使用手势?
- 创建指定手势对象,在创建时设置好当该手势发生时系统会自动调用什么方法
- 设置手势的核心属性
- 将创建好的手势添加到某个视图上,当用户在该视图上做了手势对应的动作,手势就会触发
-
Tap手势 ( 点击 )
- 核心属性:
- numberOfTapsRequired 需要点击几次
- numberOfTouchesRequired 需要几个点
- numberOfTouches 返回有几个点点击
- 核心属性:
-
Swip手势(轻扫)
- 核心属性
- direction 清扫方向
以下的手势 和 前面两个不一样,前面两个是一次性手势,手势触发一次,只调用一次时间方法,下面手势是由状态,不同状态都会调用时间方法,有以下状态:
- 核心属性
手势触发时: 起始状态
手势移动式: 改变状态
手势结束时: 结束状态
-
LongPress手势(长按)
- 核心属性
- minimumPressDuration 长按所需最小时间
- 核心属性
-
Pan(拖拽)
-
locationInView
:获取的是父视图的绝对位置 -
translationInView
: 获取的是相对于手势开始时的相对位置 (是相对位置)△x △y
-
-
Pinch手势(捏合)
- 核心属性:velocity 缩放速率
- scale 缩放比例
-
Rotation旋转
- 核心属性:rotation
-
变形
- 什么时变形:视图发生了位移,旋转,缩放这样的变化叫做变形,如何实现视图的变形.通过修改视图的transform属性,就能完成变形
-
tranform
- 类型:CGAffineTransform 结构体类型
- 该结构体中包含了9个值,是一个3*3的矩阵,矩阵的对角线上是三个定值不会发生变化,剩下的6个变量是控制变形的,可以借助系统提供的API实现数值的改变
- rotation:旋转
CGAffineTransformMakeRotation
CGAffineTransformRotation
- scale:缩放
CGAffineTranformMakeScale
CGAffineTranformScale
- translation:位移
CGAffineTranformMakeTranslation
CGAffineTranformTranslation
- 带make的函数 都是相对于初始状态
- 不带make是在变形基础上继续位移
-
CGAffineTransformIdentity
给transform属性赋值该常量,里面所有属性全部清空
-
手势加变形
- pan手势:位移
- rotation手势: 旋转
- pinch手势:缩放
- tap手势:取消所有变形效果
-
手势共存
- 需要哪个手势共存 只要设置该手势的代理人 为当前对象即可
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
- 返回一个BOOL值,为YES即可.
清空所有变形 [sender setTranslation:CGPointZero inView:self.view];
- 深入坐标系
- frame:
- CGRect类型
- 作用:定位,视图的坐定点在父视图坐标系对应点的坐标,以及视图在父视图中占据了多大的空间
- bounds
- CGRect类型
- 作用:描述了视图自身的坐标的顶点的值,以及视图自身的尺寸大小
- center
- CGPoint类型
- 描述视图的中心点在父视图坐标系的坐标位置
- transform
- CGAffineTransform类型
- 描述视图的变形状态
frame | bounds | center | transform | |
---|---|---|---|---|
frame | 改变原点:不变;改变大小:变 | 变 | 变 | |
bounds | 改变原点:不变;该大小:变 | 不变 | 不变 | |
center | 变 | 不变 | 不变 | |
transform | 不变 | 不变 | 不变 |
-
CoreAnimation层面动画
- CALayer层(显示的基础)
- backgroundColor : 设置背景颜色
- borderWidth : 设置边宽
- cornerRadius : 设置圆角半径
- borderColor : 设置边的颜色
- shadowColor : 设置阴影颜色
- shadowOffset : 设置阴影偏移量
- shadowOpacity :
设置阴影的透明度 默认为零 opacity 只会修改自己``alpha 改变父视图,会带着子视图一起变化
- shadowRadius : 设置阴影的半径
- layer.masksToBounds : 按边缘进行遮罩
- position 位置 (默认是0,0点)
- anchorPoint 锚点 (默认是 0.5,0.5)
- UIView核心的显示功能就是依赖底层的CALayer实现的,每一个UIView都包含了一个CALayer对象,修改了CALayer,会影响显示出来的UIView外观
- CALayer层(显示的基础)
-
如何获取CALayer
- 所有视图都有CALayer的属性,通过.layer即可获取
- 自己创建CALayer对象,添加到视图的layer中
-
图片CALayer
- 给contents赋值即可
-
文字CATextLayer
- 给string属性赋值即可
-
图形CAShapeLayer
- 给path属性赋值CGPath对象
-
变形
- 旋转按照锚点旋转
-
CATransform3D
类型
一个角度转弧度的宏
#define angleToRadian(x) (x) / 180.0 * M_PI
-
CADisplayLink定时器
- 用 displayLinkWithTarget 类方法创建
- 需要加到运行循环中 RunLoop
[_link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
- displayLink定时器中有一个暂停的属性
paused
.默认是NO
CALayer的很多属性都有隐式动画,在修改属性时,会自动出现动画效果,可以通过查看头文件中,属性上出现了 animatable这样的说明,意味着该属性有隐式动画
-
CAAnimation动画
- CA的动画,只能施加在CAlayer上
- CA动画是假的,视图看着好像位置改变了,但其实没有变
- UIView动画,由于明确了设定了动画的结束视图的状态,所以使徒的数据会随着动画的结束而真的被改变
-
CAAnimation 子类
- 子类一:CABasicAnimation 基础动画,设置动画的其实和中点值即可
- 一定要设置keyPath属性,以此说明动画要修改的是什么
- keyPath
- toValue 要用NSValue转换一下
- repeatCount 重复次数
- autoreverses BOOL值 是否回去
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 400)];
- duration 设置时长
-
anim.removedOnCompletion = NO;
动画结束时,是否把动画从视图上移除 -
anim.fillMode = kCAFillModeForwards;
将视图固定在动画结束时 的位置,还需要配合该属性使用------这个方法要和上面的方法配合使用kCAFillModeBackwards
在动画开始前,只需要将动画加入一个layer,layer便立即进入到动画的初始状态并等待动画的运行kCAFillModeBoth
开始和结束的两种状态都有kCAFillModeRemoved
这个是默认值,也就是说动画开始前和动画结束后动画对layer都没有影响,动画结束后layer会恢复到之前的状态kCAFillModeForwards
在动画结束时,layer停留在动画的结束状态-
子类二:CAKeyframeAnimation 关键帧动画
- 关键帧动画,可以定义动画过程中的细节,所以可以通过values属性,记录中间变化的每一个关键的细节,在每两个关键点中自动做动画
-
子类三:CAAnimationGroup
- 动画组中需要的是CAAnimation,组中动画可以同时运行
-
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
:动画组的线性函数
-
布局(Layout)
- 什么是布局:是指在一个视图中,如何摆放它的子视图(设置子视图的位置和大小)
- 为什么要用布局:屏幕的尺寸经常会发生变化,使得屏幕可显示的区域也发生变化,于是最开始添加子视图的frame,在新的区域下就不再适用了,需要进行调整,也就是需要重新布局
- 可能导致屏幕大小发生变化的原因:
- 设备不同(3.5寸下的横竖屏,4寸下横竖屏,4.7寸下的横竖屏,5.5寸下横竖屏)
- 各种bar:
- NavigationBar 竖屏是高64个点(20是状态栏),横屏是(52个点)没有状态栏;
- toolBar 竖屏是高44个点,横屏是32个点
- tabBar 49点
- 状态栏: 隐藏
- 来电时:绿色的状态栏
- 录音时:红色的状态栏
- 开启个人热点:蓝色的状态栏
- 键盘
-
如何布局:
- 纯代码布局(古老的方法)
- 理念:当屏幕发生变化时,自动执行一段代码,在代码中根据新的屏幕大小重新计算
- 纯代码布局(古老的方法)
//此方法是重写父类的方法 在屏幕内容从无到有会自动执行
//在屏幕旋转时,也会自动执行
-(void)viewDidLayoutSubviews
{
//self.topLayoutGuide.length 顶部被占据的高度
//self.bottomLayoutGuide.length 底部被占据的高度
};
- AutoResizing 布局
- 是什么? iOS5之前自动布局技术,操作简单,API简单,功能也简单,有一定的局限性,很以前的技术
- 核心理念:当视图发生变化时,
- AutoLayout(自动布局)
- 在iOS10以前配合SizeClasses技术完成屏幕的适配工作
- 工作原理:通过一些类的"约束constraint"来描述视图的展示位置
- 什么是约束?代表一个条件,只需要设定一些约束,则系统就会根据这一堆约束,自动计算符合约束的frame
- 如何创建约束?
- 方式一:用代码创建
- 方式二:在stroyBoard中 或 xib中可视化配置
- 约束的两个原则:
- 1.描述清楚(x,y,w,h)
- 2.约束不能冲突
- 约束对象:每一个约束条件都是一个约束对象
- 方法一:万能公式法
- 任何一个是视图的约束都可以由下面的等式描述出来,就是要把文字性的描述编程等式中的参数
- 方法二:VFL法(Visual Format Language
- 是一个字符串,具有一定的格式,不同的格式代表不同的约束,并且一个字符串,往往能一次性表达出多个约束
- VFL特殊符号的含义:
- | 代表父视图的边缘
- H:| 代表父视图的左边
- V:| 代表父视图的顶部
- [] 代表一个子视图(控件)
- () 条件
- -x- 代表间隔为x
- 代表间隔为标准间隔 8
- 通知:完成对象之间的消息传递(观察者模式)
- 实现的核心理念:
- 通知的发送发不知道接收方是谁,是需要将通知发给通知中心即可
- 通知的接收方不知道发送方是谁,只需要提前向通知中心订阅一个通知即可
- 一单通知的发送发真的发出了通知,则由通知中心负责将这个通知推送给所有订阅了该通知的对象们
- 应用:跨界面传值;系统之间的事情,键盘弹起等
- 与代理方式对比:
- 代理只是两个对象之间,私密的消息的传递
- 通知可以是一个对象对多个对象的消息传递,但彼此并不知道对方是谁
- 核心对象
- 通知中心:NSNotificationCenter (单例,系统自己创建好的)
- 通知 NSNotification
- 自定义通知
- 自己写通知的发送方以及接收方
- 系统提供的通知: 键盘通知
- 系统通知,系统会在适当的时候自己发通知,如果我们需要接受,只需要向通知中心注册即可,也就是说我们只需要实现接收方就可以了
- 接受键盘通知:
- 键盘将要显示 UIKeyboardWillShowNotification
- 键盘已经显示 UIKeyboardDidShowNotification
- 键盘将要隐藏 UIKeyboardWillHideNotification
- 键盘已经隐藏 UIKeyboardDidHideNotification