转载:
http://docoder.com/%E7%A7%BB%E5%8A%A8%E5%BC%80%E5%8F%91ios-uikit%E6%A1%86%E6%9E%B6/#rd
1.UIView
1.1.所有 UI 控件都继承自 UIView。
1.2.每一个 UIView 都是一个容器,可以容纳其他 UIView。其中容器视图被称为父视图,而被包含的视图或者控件被成为子视图或者子控件。
1.3.视图对应的文件通常是 storyboard 或者 xib 文件。在许多 iOS 应用程序中,通常不必为视图编写任何代码。
1.4.UIView 负责界面的显示。
1.5.常用属性:
| superview | 获得自己的父控件对象 |
| subviews | 获得自己的所有子控件对象 |
一个视图最多只能有一个父视图,一个视图可以有多个子视图。
| frame | 控件所在矩形框的位置和尺寸(以父控件的左上角为坐标原点) |
| bounds | 控件所在矩形框的位置和尺寸(以自己左上角为坐标原点,所以bounds的x和y永远为0) |
| center | 控件中点的位置(以父控件的左上角为坐标原点),通过center属性设置视图位置更加方便 |
用 frame 和 center 可以修改 UIView 的位置。
用 frame 和 bounds 可以修改 UIView 的尺寸。
通常,修改自身位置大小时使用 frame,而子视图(控件)在设置位置时,会相对父视图的 bounds 进行设置。
| tag | 控件的ID(标记),父控件可以通过tag来找到或区分子控件 |
tag 为一个整数,并且两个控件的 tag 默认为0,也可能相同。而在使用 tag 来找到或区分子控件时只会返回第一个与之相符的子控件。
| transform | 控件的形变属性(可以设置旋转角度、比例缩放、平移等属性) |
UIView 一次只能应用一个形变属性
设置 transfrom 会改变 UIView 的 frame 属性,但不会改变 bounds 属性。
CGAffineTransformMakeRotate、CGAffineTransformMakeScale、CGAffineTransformMakeTranslation 相对 UIView 的初始状态进行形变
CGAffineTransformRotate、CGAffineTransformScale、CGAffineTransformTranslation 相对 UIView 的当前状态进行形变
1.6.动画
1.6.1.UIView 封装的简单动画效果
|
1
2
3
4
5
6
|
[UIView beginAnimations:``nil
context:``nil``];
// 设置动画持续时间
[UIView setAnimationDuration:.3];
// 需要动画的代码段
// ... ...
[UIView commitAnimations];
|
1.6.2.UIView 封装的三个 block 动画方法
|
1
2
3
4
5
6
|
//1
[UIView animateWithDuration:animations:]
//2
[UIView animateWithDuration:animations:completion:]
//3
[UIView animateWithDuration: delay: options: animations: completion:]
|
1.6.3.对比 beginAnimations 动画的方式,block 动画的优势:
可以在动画完成时做一些其他的任务
可以设置动画延迟及动画效果选项
block 动画支持嵌套
2.UIButton
2.1.实例化:
2.1.1.init方式:
|
1
|
UIButton *button = [[UIButton alloc] initWithFrame:rect];
|
2.1.2.类方法方式:
|
1
|
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
其中按钮类型枚举:
| UIButtonTypeCustom | 按钮的内容需要自定义 |
| UIButtonTypeRoundedRect | 圆角矩形按钮 |
| UIButtonTypeDetailDisclosure | 显示明细按钮 |
| UIButtonTypeInfoLight | 亮色信息按钮,用于深色背景 |
| UIButtonTypeInfoDark | 深色信息按钮,用户浅色背景 |
| UIButtonTypeContactAdd | 添加按钮 |
2.2.基本设置
2.2.1.设置文字
在设置按钮文字时,需要指定文字对应的按钮状态:
|
1
2
3
4
|
//正常状态下按钮文字
[btn setTitle:``@"正常"
forState:UIControlStateNormal];
//长按按钮状态下的按钮文字
[btn setTitle:``@"长按"
forState:UIControlStateHighlighted];
|
2.2.2.设置文字颜色
在设置按钮文字颜色时,也需要指定文字对应的按钮状态:
|
1
2
|
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
|
2.2.3.设置背景颜色
|
1
|
[btn setBackgroundColor:[UIColor orangeColor]];
|
2.2.4.设置图片及背景图像
|
1
2
3
4
5
6
|
// 加载图像
UIImage *image = [UIImage imageNamed:``@"sub_black_add.png"``];
// 设置按钮图像
[btn setImage:image forState:UIControlStateNormal];
// 设置按钮背景图像
[btn setBackgroundImage:image forState:UIControlStateNormal];
|
背景图像会根据按钮的尺寸拉伸,按钮图像会居中显示在按钮中央位置。
如果同时设置了按钮的图像和文字,按钮区域足够大,会并列显示图像和文字,如果区域不够大,优先显示图像。
2.3.设置按钮点击监听
|
1
2
|
// 设置按钮点击监听
[btn addTarget:``self
action:``@selector``(tapButton) forControlEvents:UIControlEventTouchUpInside];
|
调用自定义方法需要使用 @selector 指令,按钮事件最多只可以带一个参数。
3.UILabel
3.1.实例化:
|
1
2
|
// 实例化 UILabel 并指定其边框
UILabel *label = [[UILabel alloc]initWithFrame:rect];
|
3.2.基本设置
3.2.1.设置文本
|
1
|
[label setText:``@"Hello World"``];
|
3.2.2.设置字体和字体大小
|
1
|
[label setFont:[UIFont fontWithName:``@"Helvetica-Bold"
size:40]];
|
3.2.3.设置背景色
|
1
|
[label setBackgroundColor:[UIColor greenColor]];
|
3.2.4.设置文本的颜色
|
1
|
[label setTextColor:[UIColor whiteColor]];
|
3.2.5.设置文本的阴影色彩和透明度
|
1
|
[label setShadowColor:[UIColor colorWithWhite:0.1f alpha:0.8f]];
|
3.2.6.设置阴影的偏移量
|
1
|
[label setShadowOffset:CGSizeMake(2.0f, 2.0f)];
|
3.2.7.设置文本的对齐方式
|
1
|
[label setTextAlignment:``NSTextAlignmentCenter``];
|
3.2.8.指定换行模式
|
1
|
[label setLineBreakMode:``NSLineBreakByWordWrapping``];``//按照单词换行的方式处理
|
3.2.9.指定行数,为0时没有最大行数限制
|
1
|
[label setNumberOfLines:2];
|
4.UITextField
4.1.作用:供用户输入或编辑文本
4.2.text 属性:获得或设置文本框中的文字
4.3.使用文本框控件时的注意事项:
4.3.1.在输入不同类型的文本时,需要注意键盘的类型。
4.3.2. 如果界面上有多个文本框供用户输入时,要注意回车键的设置,实现文本框由上至下的切换,切换到最后一个文本框,再按回车键时,调用对应的确认按钮的方法。
4.3.3.需要注意关闭键盘,关闭键盘有两种方法:
|
1
2
3
4
|
//1
[``self``.view endEditing:``YES``];
//2
[textField resignFirstResponder];
|
4.3.4.要监听文本框的回车事件,需要设置文本框的delegate,同时让视图控制器遵从<UITextFieldDelegate>协议。
4.4.设置键盘和键盘上面的工具栏
|
1
2
3
4
|
// 设置日期文本的输入键盘
[_dateText setInputView:datePickerView];
// 设置键盘上面的工具控件
[_dateText setInputAccessoryView:toolView];
|
4.5.常用代理方法:
|
1
2
3
4
5
6
7
8
9
10
11
|
// 当文本框开始获得焦点的时候调用
- (``void``)textFieldDidBeginEditing:
// 当用户失去焦点的时候调用
- (``void``)textFieldDidEndEditing:
// 在文本框准备聚焦的时候调用,返回NO代表不允许聚焦(编辑)
- (``BOOL``)textFieldShouldBeginEditing:
// 在文本框准备失去焦点(退出键盘)的时候调用,返回YES代表允许退出键盘
- (``BOOL``)textFieldShouldEndEditing:
// 在用户每次输入的时候都会调用,返回YES代表允许输入
- (``BOOL``)textField:
shouldChangeCharactersInRange:replacementString:
|
5.UIImageView (图像视图)
5.1.作用:
专门用来显示图片的控件
5.2.基本设置
5.2.1.设置图像
|
1
|
[``self``.imageView setImage:[UIImage imageNamed:``@"abc.png"``]];
|
5.2.2.设置显示模式
|
1
2
|
//设置图片居中显示,并且保持原来宽高比
imageView.contentMode = UIViewContentModeScaleAspectFit;
|
5.3.UIImageView的序列帧动画
5.3.1.UIImageView可以让一系列的图片在特定的时间内按顺序显示。
5.3.2.属性说明:
| animationImages | 要显示的一组图片序列 |
| animationDuration | 完整地显示所有图片所需的时间 |
| animationRepeatCount | 动画的执行次数(默认为0,代表无限循环) |
5.3.3.相关方法:
| – (void)startAnimating; | 开始动画 |
| – (void)stopAnimating; | 停止动画 |
| – (BOOL)isAnimating; | 是否正在运行动画 |
6.UISlider (滑块控件)
6.1.作用:
用来显示进度值,并且可以手动修改进度值
6.2.基本设置
|
1
2
3
4
5
6
|
// 设置滑块最大值
[slider setMaximumValue:15];
// 设置滑块最小值
[slider setMinimumValue:0];
// 设置滑块当前数值
[slider setValue:5];
|
6.3.事件监听
|
1
2
3
4
5
6
7
|
//监听 UISlider 的进度值改变,要使用 Value Changed 事件
//通过代码为 UISlider 添加监听器:
[slider addTarget:``self
action:``@selector``(sliderChange:) forControlEvents:UIControlEventValueChanged];
//当UISlider 的进度值发生改变时,会自动调用 self 的 sliderChange:方法,并且将 UISlide r作为第一个参数传入
- (``void``) sliderChange:(UISlider *)slider
{
}
|
7.UISwitch (开关控件)
7.1.作用:开关
7.2.基本设置
|
1
2
3
4
|
//设置On或者Off
[mySwitch setOn:``YES``];
//判断当前状态
BOOL
state = [mySwitch isOn];
|
7.3.事件监听
监听 UISwitch 的状态改变,要使用 Value Changed 事件(可参照 UISlider 的使用)。
8.UIStepper (计数器控件)
8.1.作用:计数
8.2.基本设置与滑块控件类似。
8.3.与滑块控件的区别:
8.3.1.每按一次减号,value 就会自动减去一定的数值(数值大小由 stepValue 决定)。
8.3.2.每按一次加号,value 就会自动增加一定的数值(数值大小由 stepValue 决定)。
8.4.事件监听
监听 UISwitch 的状态改变,要使用 Value Changed 事件(可参照 UISlider 的使用)。
9.UISegmentControl (选项卡控件)
9.1.作用:同一时刻只能选中一个标签
9.2.基本设置
|
1
2
|
NSArray
*items = @[``@"1列"``,
@"2列"``,
@"3列"``];
UISegmentedControl *control = [[UISegmentedControl alloc] initWithItems:items];
|
9.3.获得当前被选中的标签位置
|
1
|
int
index = control.selectedSegmentIndex;
|
9.4.事件监听
监听 UISwitch 的状态改变,要使用 Value Changed 事件(可参照 UISlider 的使用)。
10.UIScrollView
10.1.作用:
10.1.1.用于显示超出应用程序窗口大小的内容
10.1.2.允许用户通过拖动手势滚动查看视图中的内容
10.1.3.允许用户通过捏合手势缩放视图中的内容
10.2.常用属性:
| contentSize | 设置UIScrollView的滚动范围 |
| contentOffset | UIScrollView当前滚动的位置 |
| contentInset | 增加滚动视图四周的增加滚动范围 |
| bounces | 是否有弹簧效果 |
| scrollEnabled | 是否能滚动 |
| showsHorizontalScrollIndicator | 是否显示水平方向的滚动条 |
| showsVerticalScrollIndicator | 是否显示垂直方向的滚动条 |
| indicatorStyle | 设定滚动条的样式 |
| dragging | 是否正在被拖拽 |
| tracking | 按住手指还没有开始拖动的时候值是YES,否则NO |
| decelerating | 是否正在减速 |
| zooming | 是否正在缩放 |
10.3.属性说明
10.3.1.UIScrollView 的完整区域是在 contentSize 的四周增加 contentInset 设定的范围
10.3.2.UIScrollView 显示内容的区域由其 frame 属性决定
10.3.3.UIScrollView 显示的内容 由 contentOffset 相对 contentSize 的原点决定
10.4.ScrollView的手势缩放步骤:
10.4.1.设置 UIScrollView 的 id<UISCrollViewDelegate> delegate 代理对象。
10.4.2.设置 minimumZoomScale:缩小的最小比例
10.4.3.设置 maximumZoomScale:放大的最大比例
10.4.4.让代理对象实现以下方法,返回需要缩放的视图控件
|
1
|
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
|
与缩放相关的方法还包括:
|
1
2
3
4
|
// 正在缩放时调用的方法
- (``void``)scrollViewDidZoom:(UIScrollView *)scrollView
// 缩放完成时调用的方法
- (``void``)scrollViewDidEndZooming:(UIScrollView *)scrollView
|
10.4.5.ScrollView实现分页效果
要实现分页效果,将滚动视图的 pagingEnabled 属性设置为 YES 即可。设置该属性后滚动视图会被分割成多个独立的页面,用户原本的滚动体验会变成了页面切换的效果。
11.UIPageControl (分页控制控件)
11.1.要使用滚动视图的分页效果,通常会配合 UIPageControl 分页控制控件,以增强分页效果。
UIPageControl的页数和UIScorllView中的实际页数是分别处理的,二者之间不必一一对应。
11.2.常用属性:
| numberOfPages | 总页数 |
| currentPage | 当前的页码 |
| hidesForSinglePage | 当只有一页的时候,是否要隐藏视图 |
| currentPageIndicatorTintColor | 当前选中页面标示的颜色 |
| pageIndicatorTintColor | 其他页面标示的颜色 |
11.3.事件监听(监听页面变化)
|
1
2
3
4
|
// 添加事件监听方法
[pageControl addTarget:``self
action:``@selector``(pageChanged:) forControlEvents:UIControlEventValueChanged];
// 页面变化调用方法
- (``void``)pageChanged:(UIPageControl *)pageControl
|
12.UIDatePicker
12.1.作用:方便用户的日期选择,并保证日期格式正确
12.2.实例化:
|
1
2
|
// 实例化日期控件,不用设置宽高,因为它的宽高是固定的
UIDatePicker *datePicker = [[UIDatePicker alloc]init];
|
12.3.基本设置
|
1
2
3
4
|
// 设置日期控件区域为简体中文
[datePicker setLocale:[[``NSLocale
alloc]initWithLocaleIdentifier:``@"zh_Hans_CN"``]];
// 设置日期控件格式
[datePicker setDatePickerMode:UIDatePickerModeDate];
|
12.4.事件监听
|
1
2
|
// 设定日期控件监听方法
[datePicker addTarget:``self
action:``@selector``(dateValueChange:) forControlEvents:UIControlEventValueChanged];
|
13.UIPickerView (数据选择视图)
13.1.作用:负责从指定的数据源中选择数据
13.2.要求:使用 PickerView 之前需要指定数据源
13.2.1.数据源负责计算 UIPickerView 有多少列、多少行数据
13.2.2.数据源须遵守 UIPickerViewDataSource 协议,数据源方法如下:
|
1
2
3
4
|
// 返回总的列数
- (``NSInteger``)numberOfComponentsInPickerView:
// 返回第component列的行数
- (``NSInteger``)pickerView:numberOfRowsInComponent:
|
13.2.3刷新数据方法:
|
1
|
[pickerView reloadComponent:1];
|
一旦调用了这个方法,就会重新给数据源发送消息计算这列的行数、重新给代理发送消息获得这列的内容。
13.3.代理
13.3.1.代理可以给 UIPickerView 提供具体的数据、监听 UIPickerView 的一些事件
13.3.2.代理必须遵守 UIPickerViewDelegate 协议,常用代理方法如下:
|
1
2
3
4
5
6
7
8
|
// 第component列第row行显示什么字符串内容
- (``NSString
*)pickerView:titleForRow:forComponent:
// 每当选择了新的一行就会调用
- (``void``)pickerView:didSelectRow:inComponent:
// 第component列第row行显示什么样的UIView,最后一个view参数是用来性能优化的
- (UIView *)pickerView:viewForRow:forComponent:reusingView:
// 返回第component列每一行的高度
- (CGFloat)pickerView:rowHeightForComponent:
|
13.3.3.自定义 PickerView 时,需要指定显示选择指示器属性:
|
1
|
pickerView.showsSelectionIndicator =
YES``;
|
14.UITableView
14.1.作用:以垂直滚动方式显示数据列表。
14.2.UITableView 的两种内置样式:UITableViewStylePlain* 和 *UITableViewStyleGrouped 。
14.3.数据源 (dataSource) 和代理 (delegate)
14.3.1.UITableView 需要一个数据源(dataSource)来显示数据,UITableView 会向数据源查询一共有多少行数据以及每一行显示什么数据等。没有设置数据源的 UITableView 只是个空壳。凡是遵守UITableViewDataSource 协议的 OC 对象,都可以是 UITableView 的数据源。
|
1
2
3
4
5
6
|
// 一共有多少组数据
- (``NSInteger``)numberOfSectionsInTableView:
// 每一组有多少行数据
- (``NSInteger``)tableView:numberOfRowsInSection:
// 每一行具体显示的内容
- (UITableViewCell *)tableView:cellForRowAtIndexPath:
|
14.3.2.通常都要为 UITableView 设置代理对象(delegate),以便在 UITableView 触发一下事件时做出相应的处理,比如选中了某一行。凡是遵守了 UITableViewDelegate 协议的 OC 对象,都可以是 UITableView 的代理对象。
|
1
2
3
4
|
// 选中了某一行
(``void``)tableView:didSelectRowAtIndexPath:
// 每一行有多高
- (CGFloat)tableView:heightForRowAtIndexPath:
|
14.3.3.通常情况下,会让控制器充当 UITableView 的 dataSource 和 delegate。
14.3.4.UITableView 的每一行都是一个 UITableViewCell,通过 dataSource 的tableView:cellForRowAtIndexPath: 方法来初始化每一行。
14.3.5.UITableViewCell是UIView的子类,内部有个默认的子视图:contentView。
14.3.6.contentView是UITableViewCell显示内容的父视图,并负责显示一些辅助指示视图。
14.3.7.辅助指示视图的作用是显示一个表示动作的图标,可以通过设置UITableViewCell的accessoryType来显示,默认是UITableViewCellAccessoryNone,即不显示辅助指示视图 ,其他值如为
: UITableViewCellAccessoryDisclosureIndicator , UITableViewCellAccessoryDetailDisclosureButton和 UITableViewCellAccessoryCheckmark。
14.3.8.contentView下默认有3个子视图,其中的2个是UILabel,通过textLabel和detailTextLabel属性访问,第3个是UIImageView,通过imageView属性访问。
14.3.9.UITableViewCell的UITableViewCellStyle,用于决定使用contentView的哪些子视图,以及这些子视图在contentView中的位置。有:UITableViewCellStyleDefault , UITableViewCellStyleSubtitle, UITableViewCellStyleValue1 和 UITableViewCellStyleValue2。
14.4.UITableViewCell对象的重用原理:
14.4.1.当滚动列表时,部分 UITableViewCell 会移出窗口,UITableView 会将窗口外的 UITableViewCell 放入一个对象池中,等待重用。当 UITableView 要求 dataSource 返回 UITableViewCell 时,dataSource 会先查看这个对象池,如果池中有未使用的 UITableViewCell,dataSource 会用新的数据配置这个 UITableViewCell,然后返回给 UITableView,重新显示到窗口中,从而避免创建新对象。
14.4.2.UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象。
14.5.UITableView的编辑模式
14.5.1.UITableView属有个editing性,当设置为YES时,可以进入编辑模式。在编辑模式下,可以管理表格中的行,比如改变行的排列顺序、增加行、删除行,但不能修改行的内容。
14.5.2.开启编辑模式的方法:
|
1
2
|
@property``(``nonatomic``,getter=isEditing)
BOOL
editing;
- (``void``)setEditing:(``BOOL``)editing animated:(``BOOL``)animated;
|
14.5.3.在UITableView中删除或添加行:
|
1
2
3
4
5
6
|
//1\. 开启表格的编辑模式
//2\. 实现UITableViewDataSource的方法:
- (``void``)tableView:commitEditingStyle:forRowAtIndexPath:
//3\. 实现UITableViewDelegate的方法:
- (UITableViewCellEditingStyle)tableView: editingStyleForRowAtIndexPath:
//注意:如果不实现该方法,默认将编辑模式视为删除
|
14.5.4.移动UITableView的行:
|
1
2
3
4
|
//1\. 开启表格的编辑模式
//2\. 实现UITableViewDataSource的方法:
- (``void``)tableView:moveRowAtIndexPath:toIndexPath:
注意:只要实现了该方法,即可实现表格移动
|
14.6.四种刷新表格数据的方法:
|
1
2
3
4
5
6
7
8
|
// 新增表格数据
[tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationTop];
// 删除表格数据
[tableView deleteRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationRight];
// 局部刷新指定的行
[tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationMiddle];
// 刷新全部表格数据,如果能够准确确定被修改的数据行,就不要用此方法
[tableView reloadData];
|
14.7.常用属性
14.7.1.分隔线属性
| separatorStyle | 分隔线样式 |
| separatorColor | 分隔线颜色 |
14.7.2.选中属性
| allowsSelection | 允许选中 |
| allowsMultipleSelection | 允许多选 |
14.7.3.行数
| indexPathsForSelectedRows | 当前选中行数 |
| indexPathsForVisibleRows | 当前可见行数 |
14.7.4.背景
| backgroundView | 背景视图 |
| selectedBackgroundView | 选中时的背景视图 |
14.7.5.UITableViewCell的selectionStyle属性可设置被选中时的背景颜色:
| UITableViewCellSelectionStyleNone | 没有颜色 |
| UITableViewCellSelectionStyleBlue | 蓝色(默认) |
| UITableViewCellSelectionStyleGray | 灰色 |
14.8.自定义UITableViewCell
14.8.1.有三种方式自定义单元格:XIB , Storyboard 和 代码。
14.8.2.通过XIB或者Storyboard自定义单元格时,需要指定单元格的可重用标示符。
14.8.3.如果使用XIB方式,需要在viewDidload方法中,注册XIB文件:
|
1
2
|
UINib *nib = [UINib nibWithNibName:``@"cellName"
bundle:[``NSBundle
mainBundle]];
[``self``.tableView registerNib:nib forCellReuseIdentifier:``@"cellID"``];
|
14.8.4.在Storyboard中直接自定义单元格会注册单元格原型。
14.8.5.用代码方式自定义单元格需要注册类:
|
1
|
[tableView registerClass:[MyCell
class``] forCellReuseIdentifier:CellIdentifier];
|
14.8.6.注册单元格后,可以直接:
|
1
|
tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
|
14.9.静态表格
14.9.1.可以等同于 UIViewController 处理。
14.9.2.静态表格必须嵌入在 UITableViewController 中使用。
14.9.3.可以通过 cellForRowAtIndexPath 方法获取到用户当前选中的单元格。
14.9.4.应用场合:针对不需要发生变化的设置或者关于界面的表格视图布局。
14.9.5.静态表格无需优化处理。
14.10.提高性能建议:
14.10.1.使用可重用cell:申请内存是需要时间,特别是在一段时间内频繁的申请内存将会造成很大的开销,而且上tebleView中cell大部分情况下布局都是一样的,可以通过回收重用机制来提高性能。
14.10.2.避免content的重新布局:尽量避免在重用cell时候,对cell的内容重新布局,一般情况下,应该在创建cell的时候就将cell布局好。
14.10.3.使用不透明的subView:在定制cell的时,将要添加的subView设置成不透明的会大大减少多个view层叠加时渲染所需要的时间。
15.UISearchBar
15.1.其本身不做任何搜索,而仅是提供一个基本的iOS搜索栏界面
15.2.UISearchBar类用delegate协议的方式来告诉应用程序的其他部分,用户正在搜索栏中做什么
15.3.程序员需要自己编写对比字符串和过滤搜索的方法
15.4.实际应用中需要使用Search Bar and Search Display Controller
15.5.常用属性
| Text | 设置出现在搜索栏中的默认字符串,如果需要指定默认搜索内容时使用 |
| Placeholder | 在搜索栏没有添入任何字符串时,一般会显示一串灰色的字符来提示用户输入搜索信息 |
| Prompt | 属性值会出现在搜索栏上方。对于有复杂搜索功能的程序,用户可能需要一些指导信息 |
| Style & Tint | 设置搜索栏的样式和颜色。建议使用和UINavigationBar上同样的设置 |
| Show Search Results Button | 如果选中此选项,搜索栏右边会出现一个灰色按钮。可以用来显示最近几次的搜索,或者上次搜索的结果,通过Search Bar的代理方法可以控制该按钮的行为 |
| Show Bookmarks Button | 如果选中此选项,搜索栏右边会出现一个标准的蓝色书签按钮。用户可以调出他们储存的书签,通过Search Bar的代理方法可以控制该按钮的行为 |
| Show Cancel Button | 如果选中此选项,搜索栏右边会出现一个标准的取消按钮,让用户取消搜索。初始不要选中此选项,因为当用户在搜索栏中输入内容后,该按钮会自动出现 |
| Shows Scope Bar(显示范围栏) & Scope Titles(范围标题) | 帮助用户在指定范围内进行搜索,以缩小搜索范围 |
| Capitalize(大小写)、Correction(自动纠错)、Keyboard(键盘) | 与UITextField的属性相同,用于辅助用户输入 |
| | |
16.UIWebView
16.1.是 iOS 内置的浏览器控件,可以浏览网页、打开文档等,能够加载 html/htm、pdf、docx、txt等格式的文件,系统自带的Safari浏览器就是通过 UIWebView 实现的。
16.2.常用加载方法: loadRequest: , loadHTMLString:baseURL: , loadData:MIMEType:textEncodingName:baseURL: 。
|
1
2
3
4
5
6
7
8
|
// 使用URL字符串替代URL文本框
[_urlText setText:[url absoluteString]];
// 定义请求
NSURLRequest
*request = [``NSURLRequest
requestWithURL:url];
// 设置数据检测类型
[_webView setDataDetectorTypes:UIDataDetectorTypeAll];
// 加载请求
[_webView loadRequest:request];
|
|
1
2
3
4
5
6
7
|
// 测试加载HTML字符串
NSString
*html =
@"<html><head><title>Hello</title></head><body><h1>Hello Docoder</h1></body></html>"``;
[_webView loadHTMLString:html baseURL:``nil``];
// 测试加载部分HTML字符串,不需要显示整个网页内容时,通常使用此方法
NSString
*partHtml =
@"<h1>Hello Docoder</h1>"``;
[_webView loadHTMLString:partHtml baseURL:``nil``];
|
|
1
2
3
4
5
6
7
8
|
// 测试加载本地 PDF,需要指定 MIMETYPE
[_webView loadData:[``NSData
dataWithContentsOfFile:dataPath] MIMEType:``@"application/pdf"
textEncodingName:``@"UTF-8"
baseURL:``nil``];
// 测试加载本地文本文件,需要指定 MIMETYPE
[_webView loadData:[``NSData
dataWithContentsOfFile:dataPath] MIMEType:``@"text/plain"
textEncodingName:``@"UTF-8"
baseURL:``nil``];
// 测试加载本地HTML文件,需要指定 MIMETYPE
//baseURL是基准URL,程序要用到其他资源的位置
NSURL
*baseURL = [``NSURL
fileURLWithPath:[[``NSBundle
mainBundle]resourcePath] isDirectory:``YES``];
[_webView loadData:[``NSData
dataWithContentsOfFile:dataPath] MIMEType:``@"text/html"
textEncodingName:``@"UTF-8"
baseURL:baseURL];
|
16.3.常用导航方法:
| goBack | 回退 |
| goForward | 前进 |
| reload | 重载 |
| stopLoading | 取消载入内容 |
16.4.常用属性:
| scalespageToFit | 自动对页面进行缩放以适应屏幕 |
| dataDetectorTypes | 设定电话号码、网址、电子邮件和日期等文字变为链接文字 |
17.UIApplication
17.1.UIApplicationMain
在main.m的main函数中执行了UIApplicationMain这个方法,这是ios程序的入口点:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/*
* argc、argv:ISO C标准main函数的参数,直接传递给UIApplicationMain进行相关处理即可
* principalClassName:指定应用程序类,该类必须是UIApplication或其子类。如果为nil,则用UIApplication类作为默认值
* delegateClassName:指定应用程序类的代理类,该类必须遵守UIApplicationDelegate协议
*/
int
UIApplicationMain(``int
argc,
char
*argv[],
NSString
*principalClassName,
NSString
*delegateClassName);
/*
* 方法说明:
* 1) 由第3个参数创建一个UIApplication对象,一个程序对应一个UIApplication对象(单例),UIApplication对象是程序的象征
* 2) 由第4个参数创建一个UIApplication的delegate对象
* 3) 开启一个消息循环(不断地监听地一些系统事件)
* 4) 监听到相应的事件后,就会给代理发送相应的消息,应用程序启动完成后,首先会调用代理对象的 application:didFinishLaunchingWithOptions: 方法
*/
UIApplicationMain(argc, argv,
nil``,
NSStringFromClass``([AppDelegate
class``]));
|
17.2. UIApplication 说明
17.2.2.UIApplication 是应用程序的核心,每一个程序在运行期必须有 UIApplication (或子类)的一个实例(有且仅有一个),通过 [UIApplication sharedApplication] 可以得到这个单例实例的指针
17.2.2.UIApplication 帮助管理应用程序的生命周期,而它通过 delegate 来履行这个任务
17.2.4.UIApplication 可以接收事件,把所有用户事件都放入队列,逐个处理,它会发送当前事件给一个合适的目标控件进行处理。它还将部分事件转给 delegate 对象来处理,delegate 可处理的事件包括:应用程序的生命周期事件(如程序启动和关闭)、系统事件(如来电)。
17.2.5.在开发过程中,UIApplication 是一个非常重要的全局对象。但在实际编程中我们并不直接和UIApplication 对象打交道,而是和其代理打交道,它的代理必须遵守 UIApplicationDelegate 协议,代理提供了相关的生命周期方法来处理应用程序的系统事件
17.2.6.IOS 设备的内存极其有限,如果为 app 分配了太多内存,操作系统会终止 app 的运行,在 UIApplication 接收到这个事件后它会调用代理的 applicationDidReceiveMemoryWarning 方法,代理在这个方法内可以进行释放内存的操作以防止操作系统强制终止应用程序的运行
17.3.UIApplicationDelegate
17.3.1.ios并不是多任务的操作系统,所以app很容易受到打扰。比如一个来电可能导致app失去焦点,如果这个时候接听了电话,那么app会自动终止运行
17.3.2.还有很多其它类似的事件会导致 app 失去焦点:
app 失去焦点前会调用代理的applicationWillResignActive ;
app 再次获取焦点时会调用代理的 applicationDidBecomeActive ;
在运行 app 时锁屏会调用代理的 applicationWillResignActive;
当屏幕被解锁时,会调用代理的applicationDidBecomeActive。
17.3.3. 应用程序成为激活状态后,才可以与用户进行交互。
17.3.4. 如果要做保存游戏状态之类操作,应该在注销激活方法中处理,
因为用户可能会双击home键,打开任务栏,此时应用程序不会退出到后台!
17.3.5. 如果要做恢复游戏状态之类的操作,应该在成为激活方法中处理,
因为用户可能是从任务栏中返回的。
17.3.6. 如果应用程序运行过程中,内存或其他原因,程序被系统强行退出时,会调用Terminate方法,
开发者,可以再此记录应用程序被退出前的状态,以便改进系统
17.3.7. 应用程序退出到后台后,未必会是休眠状态,有可能会继续运行,例如:微博、QQ、音乐播放器等软件
17.3.8. 在UIKit开发中,通常不用在delegate中写内存警告方法,直接在ViewController中进行处理即可。
17.4.应用程序的完整启动过程
17.4.1.点击程序图标
17.4.2.执行main函数
17.4.3.执行UIApplicationMain函数
17.4.4.创建UIApplication对象、UIApplication的delegate对象
17.4.5.开启事件循环监听系统事件
17.4.6.程序加载完毕后调用 delegate 对象的 application:didFinishLaunchingWithOptions: 方法:创建窗口UIWindow对象;创建控制器对象;设置窗口的根控制器;让窗口成为主窗口、并且可见。
17.5.UIApplication 常用方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 设置图标右上角显示的数字
[app setApplicationIconBadgeNumber:10];
// 显示联网状态的提示,一般有网络请求时,会自动显示
[app setNetworkActivityIndicatorVisible:``YES``];
// 打开一个URL
// 在iOS中,很多东西都可以通过URL来访问,例如:电话、短信、电子邮件等
// 比如:
// 打开网站
NSURL
*url = [``NSURL
URLWithString:``@"[http://www.baidu.com](http://www.baidu.com/)"``];
[app openURL:url];
// 电话会直接呼出
NSURL
*url = [``NSURL
URLWithString:``@"[tel://10010](tel://10010)"``];
[app openURL:url];
// 会跳出短信发送界面,等待用户编辑并发送短信
NSURL
*url = [``NSURL
URLWithString:``@"[sms://10010](sms://10010)"``];
[app openURL:url];
|
18.UIWindow
18.1.UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow,但可以手动创建多个UIWindow
18.2.UIWindow的主要作用:
18.2.1.提供一个区域来显示视图
18.2.2.将事件分发给视图
18.2.3.与UIViewController协同工作,方便完成设备方向旋转的支持
18.3.将UIView添加到UIWindow中两种常见方式:
18.3.1.addSubview:直接将 UIView 添加到 UIWindow 中,程序负责维护 UIView 的生命周期以及刷新,但并不会理会 UIView 对应的 UIViewController
18.3.2.setRootViewController:自动将 UIViewController 对应的 UIView 添加到 UIWindow 中,同时负责维护 UIViewController 和 UIView 的生命周期
18.4.UIWindow常用方法:
18.4.1.makeKeyAndVisible: 让当前 UIWindow 变成 keyWindow,并显示出来
18.4.2.makeKeyWindow:让当前 UIWindow 变成 keyWindow
19.UIViewController
19.1.UIViewController 的作用:
19.1.1.创建/销毁自己的 UIView
19.1.2.显示/隐藏 UIView
19.1.3.处理 UIView 和用户之间的交互(事件处理)。
19.2.每个 UIViewController 默认都有一个 UIView 属性。
19.3.UIViewController 负责界面上元素及内容的控制与调度。
19.4.“设置”应用中的界面显示过程如下:
19.4.1.创建一个 UIViewController
19.4.2.由 UIViewController 创建自己的 UIView(懒加载)
19.4.3.把 UIView 显示到用户眼前
19.4.4.UIViewController 监听并处理 UIView的事件
19.5.loadView 方法
19.5.1.视图控制器的view懒加载(延迟加载),在使用到view时,才调用控制器的loadView方法加载view
19.5.2.loadView 加载 view 的默认过程(UIViewController的默认实现):
如果nibName有值,就会加载对应的xib文件来创建view,如果nibName没有值,优先加载同名View.xib文件来创建view,再加载同名ViewController.xib文件来创建view,如果没有找到上面所述的xib文件,就会用代码创建一个透明的view。
19.5.3.loadView 方法主要用于处理以代码的方式实现视图界面
19.5.4.如果使用storyBoard或者xib方式,不建议重写loadView方法。
19.5.5.在loadView方法中,不应该调用super loadView方法。
20.UIImagePickerController
20.1.使用 UIImagePickerController 可以选择照片。
20.2.照片的来源 UIImagePickerControllerSourceType 包括:照片库、照相机、保存的照片。
20.3.使用步骤:
20.3.1. 判断照片来源是否可用
20.3.2. 实例化照片选择控制器
20.3.3. 设置照片源
20.3.4. 设置是否允许编辑
20.3.5. 设置代理
20.3.6. 遵循协议
20.3.7. 显示照片选择控制器
20.4.照片选择代理方法
20.4.1.通过代理方法的 didFinishPickingMediaWithInfo 字典可以获取选中的照片图像
20.4.2.关闭照片选择控制器
20.4.3.保存选中的图像
21.三种创建应用程序方式小结
21.1.使用代码方式创建应用程序
21.1.1.在loadView方法中编写代码,初始化视图控件
21.1.2.在viewDidLoad方法中做数据处理
21.2.使用XIB方式创建应用程序
21.2.1.界面设计工作交由XIB文件负责
21.2.2.在viewDidLoad方法中做数据处理
21.2.3.XIB可以设置一组平行关系的视图/控制器数组,使用灵活,量级较轻
21.3.使用StoryBoard方式创建应用程序
21.3.1.界面设计工作交由StoryBoard负责
21.3.2.在viewDidLoad方法中做数据处理
21.3.3.StoryBoard主要为了方便多视图控制器之间的切换,量级较重
22.多控制器切换
22.1.视图控制器常见的切换方式:
22.1.1.Tabbar 选项卡:以 UITabbarController 为容器,以平行的方式是管理子视图控制器。
22.1.2.Push 推送:以 UINavigationController 为容器,以栈的形式管理子视图控制器。
22.1.3.Modal 模态:以模态窗口的方式显示新的视图控制器,新视图控制器关闭前,用户无法与原控制器进行交互。
22.2.容器
22.2.1.容器负责展示一个或者多个 ViewController,并管理这些ViewController的生命周期。
22.2.2.大部分容器本身也是一个 ViewController,被容器管理的这些控制器可以称为容器的子控制器 ( childViewController ),而容器可以被称为父控制器 ( parentViewController )。
22.2.3.也有极少数容器不是 ViewController,比如 UIPopoverController,其继承于 NSObject。(注:UIPopoverController 只能在iPad中使用)
22.2.4.容器可以添加、移除或切换 childViewController。
22.2.5.容器持有所有 childViewController 的实例(一般存在 NSArray 中)。
22.2.6.容器负责 childViewController 的视图生命周期方法的调用 : viewWillAppear, viewDidAppear, viewWillDisaapper, viewDidDisappear, 旋转事件等。
22.3.segue 对象的生命周期
22.3.1创建目标视图控制器。
22.3.2.创建 segue 对象并调用它的 initWithIdentifier:source:destination: 方法,其中的标示符是在 Interface Builder 中指定的唯一标示字符串,另外两个参数分别对应箭头的起始控制器和目标控制器。
22.3.3.调用源视图控制器的 prepareForSegue:sender: 方法。
22.3.4.调用 segue 对象的 perform 方法,负责将目标视图控制器推送到屏幕。
22.3.5.释放 segue 对象。
22.4.UITabbarController 和 UINavigationController 结合使用时,要先平行、再层次。
22.5.多视图控制器跳转方法:
22.5.1.Model:
打开:presentViewController:animated:completion:
关闭:dismissViewControllerAnimated:completion:
22.5.2.Push:
打开:pushViewController:animated:
关闭:popViewControllerAnimated:
22.5.3.Segue:
即可用于Modal亦可用于Push。
如果在打开目标控制器前需要做额外的处理,可以使用performSegueWithIdentifier:sender:方法。
23.UITabbarController
23.1.常用属性:
| title | 标题 |
| image | 图像(需要打开alpha通道,32*32以下,PNG格式) |
| badgeValue | 右上角的图标 |
| viewControllers | 所有子视图控制器 |
23.2.tabBarController在实例化时会加载其所有子视图控制器
24.UINavigationController
24.1.以栈的形式管理子视图控制器,只显示栈顶的视图。
24.2.常用属性:
| childViewControllers | 子视图控制器 |
| title | 标题 |
| backBarButtonItem | 返回按钮 |
| leftBarButtonItem | 左侧按钮 |
| rightBarButtonItem | 右侧按钮 |
24.3.常用方法:
| pushViewController | 将指定视图控制器压入栈顶 |
| popViewControllerAnimated | 将当前视图控制器从栈中弹出 |
25.触摸事件
25.1.UIKit可识别三种类型的输入事件:触摸事件、运动(加速计)事件、远程控制事件。
25.2.UIEvent
25.2.1.iOS 中许多事件对象都是 UIEvent 类的实例,记录事件产生的时刻和类型。
25.2.2.UIEvent 类事件类型的 enum 常量:
|
1
2
3
4
5
|
typedef
NS_ENUM``(``NSInteger``, UIEventType) {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
};
|
25.2.3.由 UIEvent 对象的 type 属性可以获取事件的类型。
25.3.响应者对象
25.3.1.在 iOS 中只有继承了 UIResponder 的对象才能接收并处理事件。我们称之为“响应者对象”。
25.3.2.UIApplication、 UIViewController、 UIView 都继承自 UIResponder,因此它们都是响应者对象,都能够接收并处理事件。
25.4.触摸事件的处理
25.4.1.UIView(所有UIKit控件均继承自 UIView )是 UIResponder 的子类,可以覆盖下列4个方法处理不同的触摸事件:
|
1
2
3
4
5
6
7
8
9
10
11
|
//1\. 一根或者多根手指开始触摸屏幕(在一次触摸事件中,只会调用一次)
- (``void``)touchesBegan:(``NSSet
*)touches withEvent:(UIEvent *)event
//2.一根或者多根手指在屏幕上移动(随着手指的移动,会持续调用该方法)
- (``void``)touchesMoved:(``NSSet
*)touches withEvent:(UIEvent *)event
//3.一根或者多根手指离开屏幕(在一次触摸事件中,只会调用一次)
//如果要调整控件的位置,可以利用 locationInView 和 previousLocationInView 计算移动差值即可
- (``void``)touchesEnded:(``NSSet
*)touches withEvent:(UIEvent *)event
//4.触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程
- (``void``)touchesCancelled:(``NSSet
*)touches withEvent:(UIEvent *)event
//注意:如果希望用户手指按下屏幕,就立刻做出反应,使用touchesBegan;如果希望用户手指离开屏幕,才做出反应,使用touchesEnded;通常情况下,应该使用touchesBegan。
|
上述4个方法都有个 UIEvent 的参数,通过 UIEvent 可以得到事件的类型和产生时间,以及当前处于活动状态的所有触摸操作。但是,通常会使用 UITouch 对象而不是 UIEvent 对象来处理触摸事件。
25.4.2.当用户触摸屏幕时,系统会创建一个 UITouch 实例,并将该对象和接触屏幕的那根手指关联。 UITouch 保存着手指在屏幕上触摸的位置。当手指移动时,系统会更新同一个 UITouch 对象,使之能够一直保存该手指在屏幕上的当前位置。当手指离开屏幕时,系统会取消相应的 UITouch 对象。
25.4.3.UITouch对象还会保存一些其他信息,比如,手指的前一个位置、手指按下屏幕的次数(tapCount, 可以用来判断单击和双击事件)。
25.4.4.因为可以有多根手指同时触发同一个事件,所以传给视图的是一组 UITouch 对象,保存在 NSSet 中,例如:如果两根手指同时触摸某个视图,那么 touchesBegan:withEvent: 的第一个参数是包含两个 UITouch 实例的 NSSet 对象;如果这两根手指一前一后分开触摸同一个视图,那么视图会收到两个独立的 touchesBegan:withEvent: 消息,并且每个 NSSet 对象中只包含一个 UITouch 对象。因此,根据 NSSet 中UITouch 的个数可以判断出是单点触摸还是多点触摸。
25.4.5.按照响应者链顺序递归查找最先处理事件的UIView,重写hitTest:withEvent:方法可以拦截触摸事件。
25.5.UITouch
25.5.1.属性
| window | 触摸产生时所处的窗口。由于窗口可能发生变化,当前所在的窗口不一定是最开始的窗口 |
| view | 触摸产生时所处的视图。由于视图可能发生变化,当前视图也不一定时最初的视图 |
| tapCount | 点按操作和鼠标的单击操作类似,tapCount表示短时间内点按屏幕的次数。因此可以根据tapCount判断单击、双击或更多的点按 |
| timestamp | 时间戳记录了触摸事件产生或变化时的时间,单位是秒 |
| phase | 触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。通过phase可以查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,是一个枚举配型,包含:
UITouchPhaseBegan(触摸开始)
UITouchPhaseMoved(接触点移动)
UITouchPhaseStationary(接触点无移动)
UITouchPhaseEnded(触摸结束)
UITouchPhaseCancelled(触摸取消) |
25.5.2.成员函数
| – (CGPoint)locationInView:(UIView *)view: | 返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置 |
| – (CGPoint)previousLocationInView:(UIView *)view: | 该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值, 表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置 |
25.6.触摸事件的传递
25.6.1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中
25.6.2.UIApplication会从事件队列中取出最前面的事件并将其分发以便处理,通常,先发送事件给应用程序的主窗口
25.6.3.主窗口会调用hitTest:withEvent:方法在视图继承树中找到一个最合适的子视图来处理触摸事件,该子视图即为hit-test视图,如果hit-test视图不处理收到的事件消息,UIKit则将事件转发到响应者链中的下一个响应者,看其是否能对该消息进行处理
25.7.响应者链
响应者链条,是通过递归构成的一组UIResponder对象的链式序列。响应者链事件处理过程为:
25.7.1.如果hit-test视图的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图。
25.7.2.如果视图或它的控制器无法处理收到的事件或消息,则将其传递给该视图的父视图。
25.7.3.每一个在视图继承树中的上层视图如果不能处理收到的事件或消息,则重复上面的步骤 24.7.1,24.7.2。
25.7.4.在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理。
25.7.5.如果window对象也不处理,则其将事件或消息传递给UIApplication对象。
25.7.6.如果UIApplication也不能处理该事件或消息,则将其丢弃。
25.8.UIView不接收处理事件的情况:
25.8.1.不接收用户交互: userInteractionEnabled = NO ;
25.8.2.隐藏: hidden = YES ;
25.8.3.透明: alpha = 0~0.01 。
26.手势识别
26.1.手势识别( Gesture Recognizer ),其目的是为了:
26.1.1.简化开发者的开发难度
26.1.2.统一用户体验
26.2.iOS 支持的手势识别:
26.2.1.UITapGestureRecognizer(点按)
26.2.2.UIPinchGestureRecognizer(捏合)
26.2.3.UIPanGestureRecognizer(拖动)
26.2.4.UISwipeGestureRecognizer(轻扫)
26.2.5.UIRotationGestureRecognizer(旋转)
26.2.6.UILongPressGestureRecognizer(长按)
26.3.手势识别的状态:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
typedef
NS_ENUM``(``NSInteger``, UIGestureRecognizerState) {
// 没有触摸事件发生,所有手势识别的默认状态
UIGestureRecognizerStatePossible,
// 一个手势已经开始但尚未改变或者完成时
UIGestureRecognizerStateBegan,
// 手势状态改变
UIGestureRecognizerStateChanged,
// 手势完成
UIGestureRecognizerStateEnded,
// 手势取消,恢复至Possible状态
UIGestureRecognizerStateCancelled,
// 手势失败,恢复至Possible状态
UIGestureRecognizerStateFailed,
// 识别到手势识别
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
};
|
也被称为离散手势,该手势识别不会被取消,只是调用一次 selector 任务。
26.4.属性:
| state | 手势状态 |
| view | 手势发生视图 |
26.5.常用方法:
| locationInView | 获得手势发生对应视图所在位置 |
| translationInView | 相对于起始位置在视图中的平移位置 |
26.6.手势使用的步骤:
26.6.1.实例化手势
26.6.2. 指定手势参数
26.6.3. 将手势附加到指定视图
26.6.4. 编写手势监听方法
26.7.imageView默认是不支持用户交互的,需要:
|
1
|
[imageView setUserInteractionEnabled:``YES``];
|
26.8.UITapGestureRecognizer (点按)
|
1
2
3
4
5
6
7
|
//点按手势 Tap
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(tap:)];
// 点按次数
[tap setNumberOfTapsRequired:2];
//双击
// 用几根手指点按
[tap setNumberOfTouchesRequired:1];
[imageView addGestureRecognizer:tap];
|
26.9.UIPinchGestureRecognizer (捏合)
|
1
2
3
|
//缩放(捏合)手势 Pinch
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(pinch:)];
[imageView addGestureRecognizer:pinch];
|
26.10.UIPanGestureRecognizer(拖动)
|
1
2
3
|
//拖动手势 Pan
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(pan:)];
[imageView addGestureRecognizer:pan];
|
26.11.UISwipeGestureRecognizer (轻扫)
26.11.1.手指在屏幕上扫动,和拖动手势的区别在于,手指离开屏幕才会触发监听方法。
26.11.2.手指可以上、下、左、右四个方向轻轻扫动,如果没有指定方向,默认都是向右扫动。
26.11.3.在设置轻扫手势时,通常需要将手势识别添加到父视图上监听。
26.11.4.在监听方法中,注意不要使用recognizaer.view,因为手势监听的是父视图,而要处理的视图通常是其他的视图。
26.11.5.如果要使用多个方向的轻扫手势,需要指定多个轻扫手势。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//轻扫手势 Swipe
//上
UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(swipe:)];
[swipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[``self``.view addGestureRecognizer:swipeUp];
//下
UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(swipe:)];
[swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[``self``.view addGestureRecognizer:swipeDown];
//左
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(swipe:)];
[swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[``self``.view addGestureRecognizer:swipeLeft];
//右
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(swipe:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[``self``.view addGestureRecognizer:swipeRight];
- (``void``)swipe:(UISwipeGestureRecognizer *)recognizer
{
// ...
if
(UISwipeGestureRecognizerDirectionUp == recognizer.direction) {
//上
// ...
}
else
if
(UISwipeGestureRecognizerDirectionDown == recognizer.direction) {
//下
// ...
}
else
if
(UISwipeGestureRecognizerDirectionLeft == recognizer.direction) {
//左
// ...
}
else
{
//右
// ...
}
// ...
}
|
26.12.UIRotationGestureRecognizer (旋转)
|
1
2
3
|
//旋转手势 Rotation
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(rotation:)];
[imageView addGestureRecognizer:rotation];
|
26.13.UILongPressGestureRecognizer (长按)
|
1
2
3
|
//长按手势 Long Press
UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc]initWithTarget:``self
action:``@selector``(longTap:)];
[imageView addGestureRecognizer:longTap];
|
27.摇晃监听
27.1.使用方法:
27.1.1.新建摇晃监听自定义视图 ,如:ShakeListenerView,并且设置 canBecomeFirstResponder 返回 YES。
27.1.2.将 ViewController 的根视图设置为自定义视图,如:ShakeListenerView。
27.1.3.在 ViewController.m 文件中增加:viewDidAppear 和 viewDidDisappear 在视图出现和消失时成为/撤销第一响应者身份。
27.1.4.在视图控制器中增加运动事件监听方法。
27.2.因为 UIResponder 的 canBecomeFirstResponder 属性,默认为 NO,而在监听摇晃事件时,需要把根视图变成第一响应者,因此常常需要自定义一个摇晃监听视图 ,如:ShakeListenerView。
<caption style="border: 0px !important; margin: 0px !important; padding: 0.5em 0px 0.5em 1em !important; vertical-align: baseline !important; border-radius: 0px !important; background: none !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 1.1em !important; outline: 0px !important; overflow: visible !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; width: auto !important; box-sizing: content-box !important; font-family: Monaco, Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-style: normal !important; font-size: 1em !important; direction: ltr !important; box-shadow: none !important; color: black !important;">ShakeListenerView.m</caption>
|
1
2
3
4
|
- (``BOOL``)canBecomeFirstResponder
{
return
YES``;
}
|
<caption style="border: 0px !important; margin: 0px !important; padding: 0.5em 0px 0.5em 1em !important; vertical-align: baseline !important; border-radius: 0px !important; background: none !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 1.1em !important; outline: 0px !important; overflow: visible !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; width: auto !important; box-sizing: content-box !important; font-family: Monaco, Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; font-weight: normal !important; font-style: normal !important; font-size: 1em !important; direction: ltr !important; box-shadow: none !important; color: black !important;">ViewController.m</caption>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
- (``void``)viewDidAppear:(``BOOL``)animated
{
[``self``.view becomeFirstResponder];
}
- (``void``)viewDidDisappear:(``BOOL``)animated
{
[``self``.view resignFirstResponder];
}
- (``void``)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if
(UIEventSubtypeMotionShake == motion) {
// 摇晃了
// ...
}
}
|