今天学习了UIScrollView和UIPageControl
UIScrollView是滚动视图
最关键的三个点
1.初始化UIScrollView的frame
2.设置UIScrollView的contentSize,contentSize的大小一定要大于frame,不管长或高,因为如果滚动范围等于frame的大小,则看不出滚动效果。
3.添加ScrollView到视图上
UIPageControl
最关键的三个点
1.初始化UIPageControl
2.设置UIPageControl的numberOfPages
3.添加到想要添加到得视图上
关于UIScrollView和UIPageControl的合作
自己做了个相册 可以滚动的相册 关键点出了上述几条之外
还有PagingEnabled是否整屏翻动的属性还有个关键的是contentOffset视图左上角距离坐标原点的偏移量。
UIScrollView的滚动相关属性
ScrollEnabled是否能够滚动 比较重要
相册的图片是可以缩放的,这就涉及到UIScrollView的缩放的几个比较重要的相关属性
minimumZoomScale 缩放的最小比例
maxmumZoomScale 放大的最大比例
zoomScale 设置变化比例
要实现缩放,还需要实现delegate,指定缩放的视图是谁。
另外UIScrollView的滚动代理方法在这里也要提一下
scrollViewDidScroll··· 滚动就会触发
scrollViewDidEndDecelerating···结束减速时触发(停时)
UIScrollView的缩放代理方法
viewForZoomingInScrollView···指定某个UIScrollView的子视图可以被放大缩小
UIPageControl与UILabel相似,用于指示当前第几页,通常与UIScrollView配合使用。
其中比较重要的属性有
currentPage 当前页 也是默认第几页
numberOfPages 指定页面的个数
UIPageControl从类名可以看出,父类是UIControl,所以可以像button一样添加事件,
只不过事件触发使用的是UIControlEvent是ValueChanged
ScrolView和PageControl的合作
通常在ScrollView滚动的时候修改PageControl的currentPage使用场景:引导页,首页的轮播图。
相册一般就是下一节的内容,视图控制器与PageControl的结合使用
总结
contentSize决定了ScrollView是否滚动,contentOffset控制内容区域的偏移量,pageEnabled控制能否整页滚动。
scrollView实现缩放需要指定最大缩放系数,最小缩放系数,并指定缩放的视图。
pageControl不单独使用,通常与ScrollView结合使用
9.8——学习第8天
今天学习了UINavigationViewController和界面通信
UINavigationViewController是一种导航控制器 与一般ViewController是存在不同的 它继承于UIViewController
导航控制器,是iOS中最常用的多视图控制器之一,它用来管理多个视图控制器。
导航控制器可以认为是管理控制器的控制器,主要管理有层级关系的控制器。
那么,接下来我们就建一个导航控制器看看,下图就是一个导航控制器的模样。
设置是后期设置的标题内容,默认是一个这样的一个长方形的视图样子。
学习导航控制器必须明白的知识点~
导航控制器是以栈的方式管理所控制的视图控制器,至少要有一个被管理的视图控制器,这个控制器我们称作,导航控制器的根视图控制器。
任何继承自UIViewController的类(多态)都可以作为根控制器。
UINavigationController通过栈的方式管理控制器的切换,控制入栈和出栈来展示各个视图控制器。
UINavigationController的ContentView里始终显示栈顶控制器的View
viewControllers属性存储了栈中的所有被管理的控制器
navigationController属性,父类中的属性,每个在栈中的控制器,都能通过此属性,获取自己所在的UINavigationController对象。
其中入栈和出栈(也就是所谓的不同层级的控制器之间的切换)的方法有
pushViewController:animated 进入下一个试图控制器
popViewController:animated:返回上一个视图控制器
popToViewController:animated 返回到指定的视图控制器
popToRootViewControllerAnimated 返回到根视图控制器
常用属性
viewControllers 所有处于栈中的控制器
topViewController 位于栈顶的控制器
visibleViewController 当前正在显示的控制器
naVigationBar导航条
说到导航控制器不得不提的是UINavigationBar
如同一个酒吧需要有自己的吧台一样,每个酒吧的样式是差不多的,但是因为吧台设计的不同使得每个酒吧也有点不一样呢。
navigationBar是什么呢? 是一个导航条,iOS7之后默认是透明的(为了看起来更加简洁),iOS7之前默认是不透明的(看起来比较逼真)。
navigationBar在透明情况,与contentView会重合一部分区域。
navigationBar在不透明情况,contentView跟在navigationBar的下面
navigationBar竖屏下默认高度是44,横屏下默认高度是32,这个就涉及到自定义导航栏的设计了,要考虑吧的是横竖屏不同情况。
navigationBar的机构
导航条可以自定义吗?这个问题问的好。
可以。
barTintColor设置导航条的颜色 注意 不是文字的颜色 也不是按钮的颜色哦 是整条导航栏的颜色呢
setBackgrundImage:forBarMetrics:导航条加背景图片,这点大家可以参考QQ的自定义界面,各种皮肤是不是很漂亮呢?
管理UINavigationItem
UiNavigationBar 除了能定义自身的样式外,还管理一组UINavigationItem。
与UINavigationController相似,UINavigationBar也是以栈的方式管理一组UINavigationItem,提供push和pop操作Item。
那么Item是个什么东西呢?
其实每个视图控制器都有一个navigationItem属性。
navigationItem中可以设置导航条上的左按钮(leftBarButtonItem)右按钮(rightBarButtonItem),标题(self.navigationItem.title=@"设置";)等
会随着控制器的显示,也显示到navigationBar上面。
UINavigationItem属于MVC中的M,封装了要显示在UINavigationBar上的数据。
看到左按钮和右按钮是不是又好气BarButtonItem是个什么鬼?
我来介绍一下吧,全名是UIBarButtonItem,它属于MVC中的M,也就是数据模型。
它定义了UINavigationItem上按钮的触发时间,外观等,
有几个方法,你们可以感受一下···
-initWithBarButtonSystemItem:target:action:
-initWithTitle:style:target:action:
-initWithImage:style:target:action:
tintColor
下面我们来介绍一下一个重要的知识点 界面间传值 这个需要你深度理解(很重要,我就不太懂)
下面介绍的是两种传值的方法,一般从第一个页面传值给第二个页面都是用属性传值,但是从第二个页面传给第一个页面就是用代理传值了。
/*
属性:
1.在第二个控制器.h文件声明传值属性
2.在第一个页面跳转第二个页面的方法中,给第二个控制器对象的传值属性赋值
3.在第二个控制器的viewDidLoad方法中,取出属性的值,放到页面上显示
代理传值:
1.在第二个控制器的.h文件声明了协议和协议方法
2.在第二个控制器的.h文件声明了delegate属性
3.在第二个控制器的.m文件中,返回上一个页面的方法中,让delegate去执行协议方法,并且把要传递的值,作为参数
4.在第一个控制器跳转到第二个控制器的方法中,secondVC.delegate = self;
5.遵守协议
6.实现协议方法,获取参数的值,放到页面上显示
*/
好了,现在我们来做一下今天的总结把~
UINavigationController 以栈的方式管理视图控制器,通过push和pop控制跳转,
这里有个小tip:后面我们还会学到模态,使用present和dismiss控制“跳转”的,不要混淆哦~
UINavigationBar管理一组UINavigationItem,UINavigationItem包含了UIBarButtonItem
使用属性传值解决从前往后传值的问题,
使用delegate解决从后往前传值的问题。
那么我学完了NavigationViewController之后做了些什么呢
做了一个结合ScrollView的相册 但是做的不够完善···
9.10——学习第9天
今天学习了UITableView表视图的一个基础
下图是成品
说说这个表视图啊,是个UI学习中的一个重点,为什么呢?从它在APP中的应用就可以看出来。
我不是做广告,我不是做广告,我不是做广告,重要的事情要说三遍!
比如美团APP 滑动的那些一条一条的团购就是一个表视图的使用。
Zaker 这个APP 每条新闻,每条资讯也是一个表视图的使用。
淘宝 每个商品还是一个表视图的使用
系统中的通讯录,也是基于表视图做出来的应用呢。
看吧,表视图在生活中的使用如此之多,你动心了嘛?
好啦,这是后事儿,我们要做的是先学好这个TableView呢
今天我们要学的内容是很重要的,这个事表视图的基础,一定要吃透哦~
表视图是干什么的呢?
前文已经提到,表视图通常用来管理一组具有相同数据结构的数据。什么新闻啊,团购啊,商品啊,是不是,当然还有通讯录。
现在开始进入正题
表视图UITableView继承子UIScrollView,所以可以滚动,对于UIScrollView不熟悉的同学请自己回顾哦~
表视图的每一条数据都是现实在UITableViewCell中,就像组成一个人需要很多很多细胞一样,表视图也需要细胞~
表视图可以区分现实数据,每个分区称为一个section,每一行称为一个row,都是从0开始的。
表视图这么好,该怎么创建呢?
其实表视图的创建和其他视图是一样的,但是也有区别,多了个样式。
UITableView *tableView=[[UITableView alloc]initWithFrame:self.bounds style:UITableViewStyleGrouped];
[self addSubview:tableView];
这里除了style样式有plain和group两种之外
还有分割线样式separatorStyle和分割线颜色separatorColor的还有rowHeight行高等重要属性。
然后把表视图添加到视图中,可是运行出来的结果完全看不到是什么情况?
其实UITableView有一个很重要的特点,把它和其他视图区分开来,那就是它有自己的DataSource 数据源。
DataSource实际上和Delegate差不多,都是要遵守一个协议,区别呢?问度娘去···
那我们接下来的操作是到ViewController里面指定表视图的数据源,然后遵守数据源的协议。
数据源是负责给TableView提供数据。
下一步我们就要实现协议方法了
1、设置组数(这里一定要说的是这是表视图的样式,有分组的也有平滑的,要分组才能看出组别呢)
2、设置行数(和组数不一样是必选的协议方法,协议分可选择的必选的方法,这个大家一定要清楚)
3、设置每行显示的什么,这就涉及到UITableViewCell,返回值一定是它,但是这里要提到的重点是cell的重用机制。
重用机制:
UITableVIew靠mutableSet来实现重用功能。
出屏幕的cell会添加到mutableSet中,即重用池,进入屏幕的cel,先从重用池中获取,如果获取不到,才创建一个cell,在cell显示之前,给cell赋上相应的内容。
cell 的reuseIdentifier是重用的关键。
下图就是一个设置每行显示什么方法的具体实现:
提到每一行显示的数据我要仔细说明一下
cell.textLable.text是显示每一行位于第一行上面的文字的。
cell.detailTextLable.text是显示每一行位于第二行上面的文字。
cell.imageView.image是显示前面那个图片的。
cell.accessoryType是选择后面是个 > 还是一个 √ 还是别的···学名叫什么’指定辅助效果样式‘,似乎然并卵···
selectionStyle是指定选中效果,具体自行分析吧···
4、设置分区标题,可选方法,这里返回值就是NSString类型的咯。
5、设置快速索引,可选方法,因为快速索引是有一个或者多个的,所以要用数组。返回值就是NSArray类型的。
进行第六步之前,我们要设置表视图的代理,然后遵循其代理协议,一般我们会和数据源一起搞定。避免忘记。
6、点击某行执行的方法,这是代理方法。一般这种的返回值是Void,记住返回值是很重要的,能提高你的工作效率。
表视图的配置问题
NSindexPath 它有几个谁能够 一个是行 row 一个是组 section
还有一个方法是 +(NSindexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section
多个分区问题
TableView默认是一个分区,可是设置多个分区
tableView的plain和group样式决定分区的样式不同。
每个分区可以设置区头区尾。
方法见下一节
总结
TableView有两种样式:plain和grouped
由DataSource提供要显示的数据,delegate提供辅助设置。
系统提供4种样式的cell
TableView的重用机制极大提升了性能。
今天暂时介绍这些。明天我们还要讲。
9.11
今天我们首先要做的是回顾昨天的内容,其次是我们今天的新内容。
今天的内容很简单,就是讲TableView的编辑操作。
编辑包括什么,一般我们都会想到,增删查改。
但是我们今天讲的是TableView的删除和移动两个操作。
删除就是前面的减号,移动就是后面的三条杠,大家应该是认识的。
下面我们先来看一下TableView的编辑 TableViewDataSource的协议方法
这是
看到左上角的编辑按钮了嘛,我们要先对他进行设置,点击编辑按钮之后会进入下面这种样子
1.让TableView处于编辑状态
-(void)setEditing:(BOOL)editing animated:(BOOL)animated;
设置编辑按钮的点击事件
//编辑按钮的点击事件
- (void)editBarButtonItemAction:(UIBarButtonItem *)sender
{
if (self.personView.tableView.editing==YES) {
sender.title=@"编辑";
}
else
{
sender.title=@"完成";
}
//设置取反状态
[self.personView.tableView setEditing:!self.personView.tableView.editing animated:YES];
}
2.设置编辑范围 这里是可选方法 一般默认是全部都可以编辑
//设置编辑范围
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// if (indexPath.section==0) {
// return NO;
// }
//默认情况下所有行都可以被编辑,当有特殊情况时进行判断,然后返回YES代表可以编辑,返回NO,代表不可以编辑
return YES;
}
3.设置编辑样式 这个就是控制前面显示的是+号还是-号(添加还是删除)
//设置编辑样式
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
//进行判断,并返回相应的删除模式
// if (indexPath.section==0) {
// return UITableViewCellEditingStyleInsert;
// }
return UITableViewCellEditingStyleDelete;
//|UITableViewCellEditingStyleInsert;
}
4.处理编辑过程 必选方法 否则实现不了删除操作(先操作数据源,在修改UI)
//处理编辑过程
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//根据indexPath.section获取key
NSString *key=self.allDataDic.allKeys[indexPath.section];
//获取数组
NSMutableArray *mutablearray=self.allDataDic[key];
//判断元素是否为一个
if (mutablearray .count==1) {
//删除分组
[self.allDataDic removeObjectForKey:key];
NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:indexPath.section];
//更新页面
[tableView deleteSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
//删除row
[mutablearray removeObjectAtIndex:indexPath.row];
//更新页面
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
这里要注意的是一定要更新页面,更新页面,更新页面,重要的事情要说三遍!!!
这样你就可以删掉一个联系人,如果这个组的联系人为空的话,就删除整个分组了。
接下来看看怎样移动吧?
移动和编辑是一样的道理
1.让TableView处于编辑状态(同上)
2.设置移动范围 可选方法 默认全部都可以移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
3.处理移动过程
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
//更新数据
//先删除再插入
//1.先获取key值
NSString *key=self.allDataDic.allKeys[sourceIndexPath.section];
//2.获取数组
NSMutableArray *mutableArray=self.allDataDic[key];
//3.获取元素
Person *person=mutableArray[sourceIndexPath.row];
//同组
if (sourceIndexPath.section==destinationIndexPath.section) {
//4.删除元素
[mutableArray removeObject:person];
//5.插入元素
[mutableArray insertObject:person atIndex:destinationIndexPath.row];
}
//不同组
else
{
//先从本来的数组中删除这个元素
[mutableArray removeObject:person];
//获取将要插入的目的分区数组的key值
NSString *key2=self.allDataDic.allKeys[destinationIndexPath.section];
//获取将要插入的目的分区数组
NSMutableArray *mutableArray2=self.allDataDic[key2];
//将移动的元素插入到目的分区的数组中
[mutableArray2 insertObject:person atIndex:destinationIndexPath.row];
//重新加载数据 被移动完的分组就消失了
if ([[self.allDataDic objectForKey:key]count]==0) {
[self.allDataDic removeObjectForKey:key];
}
[self.personView.tableView reloadData];
}
}
这里需要注明的是,一般都是同组间移动。
4.监测移动过程,实现限制跨分区移动(就是不能移动到别的分区)
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if (sourceIndexPath.section==proposedDestinationIndexPath.section) {
return proposedDestinationIndexPath;
}
else
{
return sourceIndexPath;
}
}
懒加载
//重写属性的getter方法 在setter方法中不能使用getter方法 在getter方法中不能使用setter方法
-(NSMutableDictionary *)allDataDic//setter方法
{
//懒加载
if (_allDataDic ==nil) {
self.allDataDic=[NSMutableDictionary dictionary];//setter方法
}
return _allDataDic;
}
UITableViewController
UITableViewController继承子UIViewController自带一个TableView
self.view 不是UIView而是UITableView
DataSource和delegate默认都是self(UITableViewController)
开发中只需要建立UITableViewController子类
总结
无论编辑还是移动,都先让tableView进入编辑状态。
编辑结束或者移动结束,要先修改数组或字典中的数组,再更改UI
UITableViewController是封装好了各种delegate和DataSource能提高我们的开发速度。