TreeTableView是一个非常简洁的库,用来在TableView显示树状的结构,非常棒!
github地址在这里:https://github.com/yixiangboy/TreeTableView
看样子也是我大中国同胞写的没跑了 ;)
不过俗话说的好,再好的东西不符合自身的特色也是白搭;所以难免要对其做些修改。
这里我定义了3层数据结构Group->Folder->HabitHolder,其中我们想要的效果是只显示到Folder,而不显示Folder下面的HabitHolder对象。貌似我们可以直接限制深度depth,但还有个问题是Folder可以直接显示在根目录下,即:
//情况1:
Root->Group->Folder
//情况2:
Root->Folder
所以我们不能简单判断depth(而且如果以后需求要变呢?),而是需要询问代理到底是否显示Node下面的子节点.
第一步,我们在接口中添加新的回调方法:
@protocol TreeTableCellDelegate <NSObject>
-(void)cellClick : (Node *)node;
@optional
//新建如下方法
-(BOOL)isDisplayChildrenNodesFor:(Node*)parentNode;
@end
第二步,打开代理所在类,实现之:
///不显示Folder下面的子节点
func isDisplayChildrenNodes(for parentNode: Node!) -> Bool {
if let nodeEx = parentNode as? NodeEx,nodeEx.type == .folder{
return false
}
return true
}
现在挑战来了,我么需要修改TreeTableView类的实现,在合适的地方调用我们的回调。
查看一下TreeTableView类,控制Node子项的显示主要在didSelectRowAtIndexPath方法中:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:false];
Node *parentNode = [_tempData objectAtIndex:indexPath.row];
if (_treeTableCellDelegate && [_treeTableCellDelegate respondsToSelector:@selector(cellClick:)]) {
[_treeTableCellDelegate cellClick:parentNode];
}
NSUInteger startPosition = indexPath.row+1;
NSUInteger endPosition = startPosition;
BOOL expand = NO;
for (int i=0; i<_data.count; i++) {
Node *node = [_data objectAtIndex:i];
if (node.parentId == parentNode.nodeId) {
node.expand = !node.expand;
if (node.expand) {
[_tempData insertObject:node atIndex:endPosition];
expand = YES;
endPosition++;
}else{
expand = NO;
endPosition = [self removeAllNodesAtParentNode:parentNode];
break;
}
}
}
//获得需要修正的indexPath
NSMutableArray *indexPathArray = [NSMutableArray array];
for (NSUInteger i=startPosition; i<endPosition; i++) {
NSIndexPath *tempIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPathArray addObject:tempIndexPath];
}
//插入或者删除相关节点
if (expand) {
[self insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
}else{
[self deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
}
}
参考如上代码,简单明了,作者显示判断是否要显示parentNode下面的子节点(通过expand是否为true),然后修改数据和界面。
思考下,如果我们不要显示某一parentNode下的子节点,那么上述for()子句中的判断就可以通通不要了,所有我们在for()子句上面加入如下一段代码:
//询问代理是否需要删除父节点下面的所有子节点?
if (_treeTableCellDelegate && [_treeTableCellDelegate respondsToSelector:@selector(isDisplayChildrenNodesFor:)]) {
if(![_treeTableCellDelegate isDisplayChildrenNodesFor:parentNode]){
endPosition = [self removeAllNodesAtParentNode:parentNode];
}else{
//原来的for()子句
}
}
如上,如果用户选择不显示所有子节点则只是简单将它们全部删除即可,否则按原有逻辑显示或隐藏所有子节点。
运行App,效果如下:
大家可以看到,“已完成”Folder下面是有2个子项目的,但是不会展开显示它们。而其他的树状显示逻辑保留不变,从而完美的实现了我们的要求! ;)