QQ好友列表有个很神奇的效果, 可以折叠和拉伸, 看上去很绚丽,开发中有时候我们也需要用到折叠菜单,今天就来分享一下折叠菜单的使用吧.
基本内容:
1.单行互斥折叠,既打开一行, 其他行随之关闭.
2.多行自由折叠,既每一行都可以自由代开和关闭.
基本思路:利用UITableView加载视图的基本原理和顺序,来控制每个区返回多少行.(或者通过控制每行返回的高度, 其实都是一样的, 只不过一定要注意cell上的子视图超出cell视图的情况,记得裁掉或者透明就好了,当然你要是使用每个区返回的行数来控制, 这个问题就不存在了).
UITableView的执行顺序:
1.它会调用代理方法确定有几行
[TableViewController numberOfSectionsInTableView:]
2.确定每行的表头高和表尾高(如果设定了HeardView和FooterView)
[TableViewController tableView:heightForHeaderInSection:]
[TableViewController tableView:heightForFooterInSection:]
3.确定每行有多少的cell
[TableViewController tableView:numberOfRowsInSection:]
4.然后确定每行cell的高度
[TableViewController tableView:heightForRowAtIndexPath:]
-------------如果设置多行及重复执行以上方法-----------
5.以上信息确定完毕后及调用代理方法去获取cell
[TableViewController tableView:cellForRowAtIndexPath:]
6.返回cell的高度
[TableViewController tableView:heightForRowAtIndexPath:]
7.cell将要显示到屏幕上
[TableViewController tableView:willDisplayCell:forRowAtIndexPath:]
8.cell超出屏幕进行服用时及会调用两次
[TableViewController tableView:heightForRowAtIndexPath:]
然后在进行调用 5 . 6. 7 方法
了解了UITableView的执行顺序, 我们来思考一下cell折叠的大概流程, 通常都是点击某个分组, 然后出发折叠和收合. 不错, 这个分组的位置, 正是我们每个区的头视图, 一定要记得, 分区!!!!!!!!
在区头视图返回的这个方法里:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
}
这是我们搞事情的第一步, 在这里你可以返回Button, 也可以是其他视图(记得关联方法, UIImageView的话记得打开交互), 这里不管你生成返回的是哪个View, 要记得给这个View添加tag值, 而这个值, 要跟section值有关联, 你可以是1000+section, 也可以是250+section, 什么都可以, 不过最好不要直接写section, 因为系统本身会占用一些小的tag值, 为了避免冲突, 还是写大点好. 这样, 我们就给section关联起来了.为什么要关联它呢, 有什么用呢?
当然有用! 在这个Button触发的Action里, 我们把tag值带了进去,然而又如何和我们的折叠关联起来呢?方法是有点,当我们点击Button触发方法后, 就要去刷新我们的Tableview了,但是这时候一切其实都没有改变的, 那样怎样改变呢? 不错, 就是加个全局变量(属性值也行), 在这个Action里进行赋值, 可以是tag值, 也可以是section值(即减去你自己加上去的大数1000,250,...).
/// 全局变量用于记录自己点击了哪个区,想要展开哪一区
static NSInteger mySection = 1000;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == mySection) {
//返回你要返回的行数,可能是你解析出来的数据的数组的count值, 也可能是其他, 这个自己控制, 如果还有层级关系, 可返回1, 在自定义cell方法, 继续此方法
return 1;
}else {
//没有点击就返回0(这里讲解的是互斥cell, 只展开一个区, 展开多去下面会继续分享)
return 0;
}
}
以上, 一个简单的互斥cell的展开就完成了.(还有两种方法, 有兴趣的朋友可以试一下,使用KVO进去监听, 或者使用button的selected属性去判断), 这个根据自己的洗好和擅长, 都可以实现的.
button.selected = YES;
// 或者
button.selected = NO;
/**
** 接下来我们说一下如何展开和关闭多个cell,
***/
基本思路: 与折叠一个cell大同小异, 但是不是设置一个全局变量, 而是一个数组, 去保存每区应该或者说你想让它返回的行数,当然啦, 如果你返回一个写入一个, 那么数组会好不客气的越界, 所以, 在你解析数据的方法里, 就要来给数组填充数据了,当然, 可以全是假的, 也可以全部是真的, 可以诠释0, 也是是实际的个数, 注意数组里不能添加非对象元素.
// self.dataArray 是解析数据得到的元素集合, 你的model应该偶素放在这了里面的.self.sectionAry是你自定义的来管理每个区返回多少行的数组
if (self.dataArray.count != 0) {
for (int i = 0; i<self.dataArray.count; i++) {
[self.sectionAry addObject:@NO];
}
[self.myTableView reloadData];
}
//这样, 在解析数据后, 直接就得到了每个区是否返回多少行了(也可以是实际个数, 如果你的没区不是一行).
然后, 在前面说过的透视图中Button触发的方法中, 来控制是否显示就OK了,当你点击的时候可以让他们互斥,这样点击就可以无限展开和关闭了.多个直接也不会相互影响.
- (void)aBtnAction:(UIButton *)sender{
sender.selected = !sender.selected;// 注意使用!
NSInteger newTag = sender.tag - 1000;
// 改变你点击的那个区的值,替换数组响应位置的值就可以了
[self.sectionAry replaceObjectAtIndex:newTag withObject:@(![self.sectionAry[newTag] boolValue])];
[self.myTableView reloadData];// 刷新, 便会响应改变
}
//然后, 你会在下面的方法里看到效果
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// 点击哪个, 都会响应变化, 根据需要来控制返回值.
if ([self.sectionAry[section] boolValue]) {
return 0;
}else
{
return 1;
}
}
如此, 多行同时或者不同时展开关闭也就实现了, 思想就是这些, 要注意灵活运用.有问题可留言.