ios 环境下创建树目录
来源:互联网 发布:qemu调试linux内核 编辑:程序博客网 时间:2024/06/05 05:57
需求:
最近在项目中遇到一个需求:自动读取数据库中的纪录,并根据type字段分层,构建目录树。要求能够在点击父节点的时候动态刷新子节点,并完成相关操作。
在windows 环境中,自己也做过或者用过不少目录树的控件,但是ios平台没有自带的tree目录控件,ok,自己动手写一个。
思路:
开始自己想到过简单的用几个array来动态保存每个层级的元素,例如根结点为array1,一级节点就存在array2,三级节点放在array3 ......由此类推,n级节点就放在 arrayn+1中,这样做比较简单,实现起来不复杂,但是有几个致命的缺陷:
1、在层级不能确定的前提下,需要用一个动态数组保存每一级的元素集合,也就是需要二维数组,在每一次点击节点的时候,需要至少做一次查询,并对该二维数组进行修改。实现效率较低。
2、在层级确定的前提下,可以将数组个素确定,但是如果层级发生变化,需要修改,比较麻烦。
最后,自己考虑用树来保存目录结构,并根据点击要素所在的层级,动态更新显示子节点,该方法只需要在程序加载的时候查询一次数据库,大大提高以后的点击操作效率。下图是自己简单思考后画的草图。
实现:
1、定义树形结构,作为数据目录,并将它作为界面操作的数据源
2、定义数据结构,包括节点的子节点,节点名称,以及节点度
3、定义目录在界面上的展现形式,自定义控件。
4、数据库查询操作代码。
核心代码说明:
eTreeMenu.h
@protocol eTreeMenuDelegate<NSObject>
//多选情况,title : 选择名称 sel : 是否选择
-(void)ChooseItemClick:(NSString *)title andSel:(BOOL)sel;
//清除已经选择的叶子节点
-(void)clearChoosedLeaves;
@end
@interface eTreeNode : NSObject
{
eTreeNode *parentNode;
NSArray *childrenNode;
NSString *displayName;
NSInteger nodeDepth;
}
@property(nonatomic,assign) NSInteger nodeDepth;
@property(nonatomic,retain)NSString *displayName;
@property(nonatomic,retain)NSArray *childrenNode;
@property(nonatomic,retain)eTreeNode *parentNode;
@end
@interface eTreeMenu : UIScrollView<eChooseItemViewDelegate>
{
id<eTreeMenuDelegate> sdelegate;
NSMutableDictionary *dataSource;
eTreeNode *rootNode;
NSInteger depth;
float maxWidth;
float maxHeight;
sqliteCommand *sqlComd;
NSMutableArray *showNodes;
eTreeNode *Root;
//选中的node深度
NSInteger selectedNodeDepth;
}
@property(nonatomic,retain)id<eTreeMenuDelegate> sdelegate;
@property(nonatomic,retain)eTreeNode *Root;
@property(nonatomic,retain)NSMutableArray *showNodes;
@property(nonatomic,retain)sqliteCommand *sqlComd;
@property(nonatomic,assign) NSInteger depth;
@property(nonatomic,retain)eTreeNode *rootNode;
@property(nonatomic,retain)NSMutableDictionary *dataSource;
@end
eTreeMenu.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setTreeData];
//self.backgroundColor=[UIColor lightGrayColor];
}
return self;
}
- (id)initWithFrame:(CGRect)frame andData:(NSMutableDictionary *)data
{
self.dataSource=data;
self = [super initWithFrame:frame];
if (self) {
self.depth=0;
}
return self;
}
//设定数据
-(void)setTreeData
{
[self loadAreaData];
[self initShowNodeWithRoot];
[self redrawWithNode:self.Root andSelectNode:nil];
}
//加载数据目录
-(void)loadAreaData
{
eTreeNode *root=[self createNodeWithCode:@"900000" andName:@"中国" withDepth:1];
self.Root=root;
}
//利用递归方法实现各个节点
-(eTreeNode *)createNodeWithCode:(NSString *)code andName:(NSString *)dispName withDepth:(int)curDepth
{
eTreeNode *node;
NSString *tableName=@"TAB_AREACODE_NEW";
NSArray *cols=[NSArray arrayWithObjects:@"MC",@"CODE",@"PARENT", nil];
//更新树的深度
self.depth=5;//(self.depth<curDepth)?curDepth:self.depth;
if (self.sqlComd==nil) {
NSString *dbDir=[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"/DB/"];
self.sqlComd= [[sqliteCommand alloc] initSqlLiteParam:dbDir andFile:ANALYSIS_DB_NAME];
}
NSArray *array=[self.sqlComd getValuesFromSqlite:tableName andCols:cols andAdopter:[NSString stringWithFormat:@" TYPE =%d AND PARENT=%@",curDepth+1,code]];
if (array==nil||[array count]<=0) {
//没有子节点是叶子
node=[[eTreeNode alloc] initWithParent:nil andChildren:nil andName:dispName andDepth:curDepth];
}else
{
//还有子节点
NSMutableArray *childs=[[NSMutableArray alloc] init];
for (int i=0; i<[array count]; i++) {
NSString *_title=[[array objectAtIndex:i] objectAtIndex:0];
NSString *_code=[[array objectAtIndex:i] objectAtIndex:1];
eTreeNode *childNode=[self createNodeWithCode:_code andName:_title withDepth:curDepth+1];
[childs addObject:childNode];
}
node=[[eTreeNode alloc] initWithParent:nil andChildren:childs andName:dispName andDepth:curDepth];
}
return node;
}
//绘制部分代码
//由根节点,生成树,created by eric 20140115
-(void)initShowNodeWithRoot
{
//重新申明
showNodes=[[NSMutableArray alloc] initWithCapacity:self.depth];
if (self.Root!=nil) {
eTreeNode *node=self.Root;
for (int i=0; i<self.depth; i++) {
[showNodes addObject:node];
if (node!=nil && node.childrenNode!=nil) {
//子目录不为空,默认选择第一个
node=[node.childrenNode objectAtIndex:0];
}else
{
node=nil;
}
}
}
}
//重新绘制,根据node节点为主,并选择节点 selNode
-(void)redrawWithNode:(eTreeNode *)parentNode andSelectNode:(eTreeNode *)selNode
{
for (id view in self.subviews) {
[view removeFromSuperview];
}
eTreeNode *tempNode=(selNode==nil)?parentNode:selNode;
if (showNodes!=nil) {
//之前的层级保持不变
for (int i=0; i<tempNode.nodeDepth-1; i++) {
eTreeNode *nd=[showNodes objectAtIndex:i];
[self addLeaves:nd andDepth:i andSelect:[showNodes objectAtIndex:i+1]];
}
//当前层级发生变化
for (int i=tempNode.nodeDepth-1; i<self.depth-1; i++) {
[self addLeaves:tempNode andDepth:i andSelect:tempNode];
[showNodes setObject:tempNode atIndexedSubscript:i];
if (tempNode!=nil && tempNode.childrenNode!=nil) {
//子目录不为空,默认选择第一个
tempNode=[tempNode.childrenNode objectAtIndex:0];
}else
{
tempNode=nil;
}
}
}
}
//添加叶子节点,node:节点要素 depth:节点深度 ,并选择节点selNode
-(void)addLeaves:(eTreeNode *)node andDepth:(NSInteger )nodeDepth andSelect:(eTreeNode *)selNode
{
NSLog(@"draw the depth:%d",nodeDepth);
if (nodeDepth>=0) {
if (node.childrenNode!=nil) {
float butWidth=140.0;
float butHeight=32.0;
float offsetX=0.0;
float offsetY=0.0;
//maxHeight=(maxHeight>nodeDepth * butHeight)?maxHeight:nodeDepth * butHeight;
//maxWidth=(maxWidth>[node.childrenNode count]*butWidth)?maxWidth:[node.childrenNode count]*butWidth;
for (int i=0; i<[node.childrenNode count]; i++) {
eTreeNode *item=[node.childrenNode objectAtIndex:i];
eChooseItemView *nodeItem=[[eChooseItemView alloc] initWithFrame:CGRectMake(offsetX+(butWidth+4)*i, offsetY+(butHeight+5)*nodeDepth, butWidth, butHeight) andTile:item.displayName];
NSLog(@".....added the item:%@",item.displayName);
nodeItem.nodeData=item;
nodeItem.parentNode=node;
[self addSubview:nodeItem];
if (item.nodeDepth==selNode.nodeDepth&&[item.displayName isEqualToString:selNode.displayName]) {
[nodeItem changeMode];
}
nodeItem.delegate=self;
}
//设定视图大小
self.contentSize=CGSizeMake(([node.childrenNode count]+1)*butWidth, nodeDepth * butHeight);
}
}
}
//添加叶子节点,node:节点要素 depth:节点深度
-(void)addLeaves:(eTreeNode *)node andDepth:(NSInteger )nodeDepth
{
if (nodeDepth>=0) {
if (node.childrenNode!=nil) {
float butWidth=140.0;
float butHeight=32.0;
float offsetX=0.0;
float offsetY=0.0;
//maxHeight=(maxHeight>nodeDepth * butHeight)?maxHeight:nodeDepth * butHeight;
//maxWidth=(maxWidth>[node.childrenNode count]*butWidth)?maxWidth:[node.childrenNode count]*butWidth;
for (int i=0; i<[node.childrenNode count]; i++) {
eTreeNode *item=[node.childrenNode objectAtIndex:i];
eChooseItemView *nodeItem=[[eChooseItemView alloc] initWithFrame:CGRectMake(offsetX+(butWidth+4)*i, offsetY+(butHeight+5)*nodeDepth, butWidth, butHeight) andTile:item.displayName];
NSLog(@".....added the item:%@",item.displayName);
nodeItem.nodeData=item;
nodeItem.parentNode=node;
[self addSubview:nodeItem];
nodeItem.delegate=self;
}
//设定视图大小
self.contentSize=CGSizeMake(([node.childrenNode count]+1)*butWidth, nodeDepth * butHeight);
}
}
}
-(void)ChooseItemClick:(UIButton *)sender andSel:(BOOL)sel andTitle:(NSString *)title
{
eChooseItemView *send=(eChooseItemView *)sender;
if (send.nodeData.nodeDepth != self.depth )
{
[self redrawWithNode:send.parentNode andSelectNode:send.nodeData];
[self redrawWithNode:send.parentNode andSelectNode:send.nodeData];
}
//如果选中节点是之前节点的子节点,清除之前选中项目
if (selectedNodeDepth<send.nodeData.nodeDepth) {
[self.sdelegate clearChoosedLeaves];
}
selectedNodeDepth=send.nodeData.nodeDepth;
[self.sdelegate ChooseItemClick:title andSel:sel];
}
-(void)dealloc
{
[dataSource release];
[rootNode release];
[sqlComd release];
[showNodes release];
[Root release];
[super dealloc];
}
@end
展示效果:
补充:
1、相关代码已经上传到csdn,欢迎各位下载。下载地址: http://download.csdn.net/detail/xwz19861215311x/6858163
2、由于时间关系,代码没有做优化,存在一些bug,欢迎各位批评指正。(QQ:435011569)
- ios 环境下创建树目录
- IOS 创建目录/文件夹
- ios NSFileManager创建目录、文件
- linux下创建目录技巧
- linux下批量创建目录
- UNICODE下创建多层目录
- Linux下递归创建目录
- linux下逐级创建目录
- Linux下递归创建目录
- windows下循环创建目录
- Linux下创建FTP目录
- 如何创建iOS环境下的cordova插件,让其运用到iOS项目中
- IOS的一些文件操作。(沙箱) 在Documents目录下创建文件
- IOS的一些文件操作。(沙箱) 在Documents目录下创建文件
- vue-cnodejs学习-目录创建 环境配置
- es6环境搭建(1)目录创建。
- es6环境搭建(1)目录创建
- ios下App目录详解
- android 系统时间转换
- loopback_device
- android面试经1
- win7下windbg无法找到正确调试符号问题
- 使用Unity VS进行调试
- ios 环境下创建树目录
- 截获BM_SETSTYLE:自绘按钮控件属性自绘属性的保持
- How to Generate an AWR Report and Create Baselines (文档 ID 748642.1)
- sqlserver距当天时差
- Javascript 操作select控件大全(新增、修改、删除、选中、清空、判断存在等)
- LINUX 下USB摄像头设置
- $(document).Ready()方法 VS OnLoad事件 VS $(window).load()方法
- Failure [INSTALL_FAILED_OLDER_SDK]
- Qt之透明提示框(模拟QQ)