重写Github的TreeTableView库实现定制显示子节点

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个子项目的,但是不会展开显示它们。而其他的树状显示逻辑保留不变,从而完美的实现了我们的要求! ;)

猜你喜欢

转载自blog.csdn.net/mydo/article/details/80648097