IOS树视图学习总结
生活随笔
收集整理的這篇文章主要介紹了
IOS树视图学习总结
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
iOS: 查看 UIView 的視圖樹
http://www.cnblogs.com/ihojin/p/view-recursivedescription.html在想要查看的 UIView 附近打個斷點,運行,直到停在斷點處,在控制臺鍵入:po [view recursiveDescription],回車。
(lldb) po [self recursiveDescription]
<BPSearchBar: 0xaab5fe0; baseClass = UISearchBar; frame = (114 0; 500 44); text = ''; opaque = NO; autoresize = LM+RM+TM; gestureRecognizers = <NSArray: 0xaab7c80>; layer = <CALayer: 0xaab6210>>
? ?| <UIView: 0xaab7470; frame = (0 0; 500 44); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0xaab74d0>>
? ?| ? ?| <UISearchBarBackground: 0xaab7f90; frame = (0 0; 500 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xaab80e0>>
? ?| ? ?| <UISearchBarTextField: 0xaab8bf0; frame = (8 8; 484 28); text = ''; clipsToBounds = YES; opaque = NO; gestureRecognizers = <NSArray: 0xb9c4a30>; layer = <CALayer: 0xaab8d80>>
? ?| ? ?| ? ?| <UITextFieldBorderView: 0xb9d37e0; frame = (0 0; 484 28); opaque = NO; layer = <CALayer: 0xb9d38f0>>
? ?| ? ?| ? ?| <UIImageView: 0xaabb4c0; frame = (232 7.5; 12.5 12.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xaabb0e0>>
(lldb)?
========
iOS樹狀視圖(折疊單元格)詳細使用
http://blog.csdn.net/hbblzjy/article/details/51954493RATreeView是一個第三方的iOS樹視圖(通俗的講就是折疊單元格),它是對UITableView的封裝,定義自己的委托和數(shù)據(jù)源的法,RATreeView是高度可定制的,并且有很多功能。很多朋友都說使用的不好,官方講的也不夠詳細,所以我就給大家講一下,怎么使用.
首先先看下實現(xiàn)效果
1.gif
使用方法
CocoaPods pod 'RATreeView', '~> 2.1.0'
具體使用
1.創(chuàng)建model
#import <Foundation/Foundation.h>
@interface RaTreeModel : NSObject
@property (nonatomic,copy) NSString *name;//標題
@property (nonatomic,strong) NSArray *children;//子節(jié)點數(shù)組
//初始化一個model
- (id)initWithName:(NSString *)name children:(NSArray *)array;
//遍歷構(gòu)造器
+ (id)dataObjectWithName:(NSString *)name children:(NSArray *)children;
@end
#import "RaTreeModel.h"
@implementation RaTreeModel
- (id)initWithName:(NSString *)name children:(NSArray *)children
{
? ? self = [super init];
? ? if (self) {
? ? ? ? self.children = children;
? ? ? ? self.name = name;
? ? }
? ? return self;
}
+ (id)dataObjectWithName:(NSString *)name children:(NSArray *)children
{
? ? return [[self alloc] initWithName:name children:children];
}
@end
2.創(chuàng)建cell
特別注意 xib創(chuàng)建的cell, 一定不要勾選Use Auto Layout,否則cell上的布局不會執(zhí)行.
找不到的,請看下圖
Snip20160525_1.png
cell創(chuàng)建具體如下:
這是我用xib設(shè)置的cell,你們按照你們的需求做
Snip20160525_4.png
#import <UIKit/UIKit.h>
@interface RaTreeViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *iconView;//圖標
@property (weak, nonatomic) IBOutlet UILabel *titleLable;//標題
//賦值
- (void)setCellBasicInfoWith:(NSString *)title level:(NSInteger)level children:(NSInteger )children;
@end
#import "RaTreeViewCell.h"
@interface RaTreeViewCell ()
@end
@implementation RaTreeViewCell
- (void)awakeFromNib {
? ? // Initialization code
? ? self.selectionStyle = UITableViewCellSelectionStyleNone;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
? ? [super setSelected:selected animated:animated];
? ? // Configure the view for the selected state
}
- (void)setCellBasicInfoWith:(NSString *)title level:(NSInteger)level children:(NSInteger )children{
? ? //有自孩子時顯示圖標
? ? if (children==0) {
? ? ? ? self.iconView.hidden = YES;
? ? }
? ? else { //否則不顯示
? ? ? ? self.iconView.hidden = NO;
? ? }
? ? self.titleLable.text = title;
? ? self.iconView.image = [UIImage imageNamed:@"close"];
? ? //每一層的布局
? ? CGFloat left = 10+level*30;
? ? //頭像的位置
? ? CGRect ?iconViewFrame = self.iconView.frame;
? ? iconViewFrame.origin.x = left;
? ? self.iconView.frame = iconViewFrame;
? ? //title的位置
? ? CGRect titleFrame = self.titleLable.frame;
? ? titleFrame.origin.x = 40+left;
? ? self.titleLable.frame = titleFrame;
}
3.創(chuàng)建RATreeView
只展示核心代碼
數(shù)據(jù)
//加載數(shù)據(jù)
- (void)setData {
? ? //寶雞市 (四層)
? ? RaTreeModel *zijingcun = [RaTreeModel dataObjectWithName:@"紫荊村" children:nil];
? ? RaTreeModel *chengcunzheng = [RaTreeModel dataObjectWithName:@"陳村鎮(zhèn)" children:@[zijingcun]];
? ? RaTreeModel *fengxiang = [RaTreeModel dataObjectWithName:@"鳳翔縣" children:@[chengcunzheng]];
? ? RaTreeModel *qishan = [RaTreeModel dataObjectWithName:@"岐山縣" children:nil];
? ? RaTreeModel *baoji = [RaTreeModel dataObjectWithName:@"寶雞市" children:@[fengxiang,qishan]];
? ? //西安市
? ? RaTreeModel *yantaqu = [RaTreeModel dataObjectWithName:@"雁塔區(qū)" children:nil];
? ? RaTreeModel *xinchengqu = [RaTreeModel dataObjectWithName:@"新城區(qū)" children:nil];
? ? RaTreeModel *xian = [RaTreeModel dataObjectWithName:@"西安" children:@[yantaqu,xinchengqu]];
? ? RaTreeModel *shanxi = [RaTreeModel dataObjectWithName:@"陜西" children:@[baoji,xian]];
? ? [self.modelArray addObject:shanxi];
}
#代理方法
#pragma mark -----------delegate?
//返回行高
- (CGFloat)treeView:(RATreeView *)treeView heightForRowForItem:(id)item {
? ? return 50;
}
//將要展開
- (void)treeView:(RATreeView *)treeView willExpandRowForItem:(id)item {
? ? RaTreeViewCell *cell = (RaTreeViewCell *)[treeView cellForItem:item];
? ? cell.iconView.image = [UIImage imageNamed:@"open"];
}
//將要收縮
- (void)treeView:(RATreeView *)treeView willCollapseRowForItem:(id)item {
? ? RaTreeViewCell *cell = (RaTreeViewCell *)[treeView cellForItem:item];
? ? cell.iconView.image = [UIImage imageNamed:@"close"];
}
//已經(jīng)展開
- (void)treeView:(RATreeView *)treeView didExpandRowForItem:(id)item {
? ? NSLog(@"已經(jīng)展開了");
}
//已經(jīng)收縮
- (void)treeView:(RATreeView *)treeView didCollapseRowForItem:(id)item {
? ? NSLog(@"已經(jīng)收縮了");
}
# dataSource方法
//返回cell
- (UITableViewCell *)treeView:(RATreeView *)treeView cellForItem:(id)item {
? ? //獲取cell
? ? RaTreeViewCell *cell = [treeView dequeueReusableCellWithIdentifier:@"RaTreeViewCell"];
? ? //當(dāng)前item
? ? RaTreeModel *model = item;
? ? //當(dāng)前層級
? ? NSInteger level = [treeView levelForCellForItem:item];
? ? //賦值
? ? [cell setCellBasicInfoWith:model.name level:level children:model.children.count];
? ? return cell;
}
/**
?* ?必須實現(xiàn)
?*
?* ?@param treeView treeView
?* ?@param item ? ?節(jié)點對應(yīng)的item
?*
?* ?@return ?每一節(jié)點對應(yīng)的個數(shù)
?*/
- (NSInteger)treeView:(RATreeView *)treeView numberOfChildrenOfItem:(id)item
{
? ? ?RaTreeModel *model = item;
? ? ?if (item == nil) {
? ? ? ? return self.modelArray.count;
? ? }
? ? return model.children.count;
}
/**
?*必須實現(xiàn)的dataSource方法
?*
?* ?@param treeView treeView
?* ?@param index ? ?子節(jié)點的索引
?* ?@param item ? ? 子節(jié)點索引對應(yīng)的item
?*
?* ?@return 返回 節(jié)點對應(yīng)的item
?*/
- (id)treeView:(RATreeView *)treeView child:(NSInteger)index ofItem:(id)item {
? ? RaTreeModel *model = item;
? ? if (item==nil) {
? ? ? ? return self.modelArray[index];
? ? }
? ? return model.children[index];
}
//cell的點擊方法
- (void)treeView:(RATreeView *)treeView didSelectRowForItem:(id)item {
? ? //獲取當(dāng)前的層
? ? NSInteger level = [treeView levelForCellForItem:item];
? ? //當(dāng)前點擊的model
? ? RaTreeModel *model = item;
? ? NSLog(@"點擊的是第%ld層,name=%@",level,model.name);
}
//單元格是否可以編輯 默認是YES
- (BOOL)treeView:(RATreeView *)treeView canEditRowForItem:(id)item {
? ? return YES;
}
//編輯要實現(xiàn)的方法
- (void)treeView:(RATreeView *)treeView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowForItem:(id)item {
? ? NSLog(@"編輯了實現(xiàn)的方法");
}
4.基本能用到的方法 我都寫了注釋,如有錯誤請指出.是不是比官方的清楚的多.
demo地址:http://download.csdn.net/detail/hbblzjy/9580054
========
iOS 選擇樹實現(xiàn) SinTreeCheckView
因為項目需要實現(xiàn)一個分類選擇的樹,所以查了不少代碼,感覺不合適就自己實現(xiàn)了一個。
下面是效果截圖:
源代碼在我的百度網(wǎng)盤:SinTreeCheckDemo.zip
http://pan.baidu.com/share/link?uk=201730971&shareid=489#dir/path=%2F源代碼%2FiOS
========
iOS樹��形結(jié)構(gòu)TreeTableView
http://www.jianshu.com/p/de5d591d02ed/comments/1740406TreeTableView
一、簡介
樹形控件在多列列表、多級菜單中使用比較常見,比如:國家-省份-城市 多級選擇、學(xué)校-專業(yè)-班級 多級選擇等等。然而IOS自帶控件中并不存在樹形控件,我們要在IOS開發(fā)中使用樹形控件,通常需要自己擴展UITableView列表控件。<br/>現(xiàn)在在這里開源一個自己寫的高擴展性,高復(fù)用性的IOS樹形結(jié)構(gòu)控件。<br/>支持無限極樹形結(jié)構(gòu)。<br/>使用的是非遞歸方式。<br/>代碼簡單易懂,擴展方便。<br/>圖片演示如下:
項目演示
<br/>
<br/>
二、使用說明
第一步:建立數(shù)據(jù)模型
parentId : 該節(jié)點的父控件id號,如果為-1則表示該節(jié)點為根節(jié)點<br/>
nodeId : 每個節(jié)點自身的id號,是每個節(jié)點的唯一標示<br/>
name : 節(jié)點的名稱<br/>
depth : 該節(jié)點所帶的樹形結(jié)構(gòu)中的深度,根節(jié)點的深度為0<br/>
expand : 該節(jié)點是否處于展開狀態(tài)<br/>
/**
* ?每個節(jié)點類型
*/
@interface Node : NSObject
@property (nonatomic , assign) int parentId;//父節(jié)點的id,如果為-1表示該節(jié)點為根節(jié)點
@property (nonatomic , assign) int nodeId;//本節(jié)點的id
@property (nonatomic , strong) NSString *name;//本節(jié)點的名稱
@property (nonatomic , assign) int depth;//該節(jié)點的深度
@property (nonatomic , assign) BOOL expand;//該節(jié)點是否處于展開狀態(tài)
/**
*快速實例化該對象模型
*/
- (instancetype)initWithParentId : (int)parentId nodeId : (int)nodeId name : (NSString *)name depth : (int)depth expand : (BOOL)expand;
@end
第二步:按照以上的數(shù)據(jù)模型,組裝數(shù)據(jù),下面以 國家-身份-城市 的三級目錄進行演示。
//----------------------------------中國的省地市關(guān)系圖3,2,1--------------------------------------------
Node *country1 = [[Node alloc] initWithParentId:-1 nodeId:0 name:@"中國" depth:0 expand:YES];
Node *province1 = [[Node alloc] initWithParentId:0 nodeId:1 name:@"江蘇" depth:1 expand:NO];
Node *city1 = [[Node alloc] initWithParentId:1 nodeId:2 name:@"南通" depth:2 expand:NO];
Node *city2 = [[Node alloc] initWithParentId:1 nodeId:3 name:@"南京" depth:2 expand:NO];
Node *city3 = [[Node alloc] initWithParentId:1 nodeId:4 name:@"蘇州" depth:2 expand:NO];
Node *province2 = [[Node alloc] initWithParentId:0 nodeId:5 name:@"廣東" depth:1 expand:NO];
Node *city4 = [[Node alloc] initWithParentId:5 nodeId:6 name:@"深圳" depth:2 expand:NO];
Node *city5 = [[Node alloc] initWithParentId:5 nodeId:7 name:@"廣州" depth:2 expand:NO];
Node *province3 = [[Node alloc] initWithParentId:0 nodeId:8 name:@"浙江" depth:1 expand:NO];
Node *city6 = [[Node alloc] initWithParentId:8 nodeId:9 name:@"杭州" depth:2 expand:NO];
//----------------------------------美國的省地市關(guān)系圖0,1,2--------------------------------------------
Node *country2 = [[Node alloc] initWithParentId:-1 nodeId:10 name:@"美國" depth:0 expand:YES];
Node *province4 = [[Node alloc] initWithParentId:10 nodeId:11 name:@"紐約州" depth:1 expand:NO];
Node *province5 = [[Node alloc] initWithParentId:10 nodeId:12 name:@"德州" depth:1 expand:NO];
Node *city7 = [[Node alloc] initWithParentId:12 nodeId:13 name:@"休斯頓" depth:2 expand:NO];
Node *province6 = [[Node alloc] initWithParentId:10 nodeId:14 name:@"加州" depth:1 expand:NO];
Node *city8 = [[Node alloc] initWithParentId:14 nodeId:15 name:@"洛杉磯" depth:2 expand:NO];
Node *city9 = [[Node alloc] initWithParentId:14 nodeId:16 name:@"舊金山" depth:2 expand:NO];
//----------------------------------日本的省地市關(guān)系圖0,1,2--------------------------------------------
Node *country3 = [[Node alloc] initWithParentId:-1 nodeId:17 name:@"日本" depth:0 expand:YES];
NSArray *data = [NSArray arrayWithObjects:country1,province1,city1,city2,city3,province2,city4,city5,province3,city6,country2,province4,province5,city7,province6,city8,city9,country3, nil];
第三步:使用以上數(shù)據(jù)進行TeeTableView的初始化。
TreeTableView *tableview = [[TreeTableView alloc] initWithFrame:CGRectMake(0, 20, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)-20) withData:data];
[self.view addSubview:tableview];
通過簡單以上三步,你就可以把該樹形控件集成到你的項目中。
<br/>
<br/>
三、實現(xiàn)原理
樹形結(jié)構(gòu)的列表用的其實就是UITableView控件,但是如何能夠讓UItableView能夠動態(tài)的增加和刪除指定的行數(shù)的cell是實現(xiàn)樹形結(jié)構(gòu)的關(guān)鍵所在。
這時候我們需要用到兩個UItableView自帶的行數(shù):
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
第一個函數(shù)用來在指定的位置插入cells,第二個函數(shù)用來在指定的位置刪除cells,并且這二個函數(shù)都自帶多種動畫效果,讓刪除和插入的過程不至于太突兀、有種漸變的感覺,具有良好的用戶體驗。
對于這幾個動畫做了嘗試:
UITableViewRowAnimationFade : 漸變效果
UITableViewRowAnimationRight : 右邊進入,右邊消失
UITableViewRowAnimationLeft : 左邊進入,左邊消失
UITableViewRowAnimationTop : 頂部進入,頂部消失
UITableViewRowAnimationBottom : 頂部進入,底部消失
<font color=red>注意點:</font>
在調(diào)用insertRowsAtIndexPaths和deleteRowsAtIndexPaths的時候一定要先改變數(shù)據(jù)源,在調(diào)用上述函數(shù),不然會產(chǎn)生crash。
接下來把TreeTableView的主要代碼展示出來,因為本來代碼量就不大,而且代碼中注釋也比較全,希望能夠幫助大家理解。
#import "TreeTableView.h"
#import "Node.h"
@interface TreeTableView ()<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic , strong) NSArray *data;//傳遞過來已經(jīng)組織好的數(shù)據(jù)(全量數(shù)據(jù))
@property (nonatomic , strong) NSMutableArray *tempData;//用于存儲數(shù)據(jù)源(部分數(shù)據(jù))
@end
@implementation TreeTableView
-(instancetype)initWithFrame:(CGRect)frame withData : (NSArray *)data{
self = [super initWithFrame:frame style:UITableViewStyleGrouped];
if (self) {
self.dataSource = self;
self.delegate = self;
_data = data;
_tempData = [self createTempData:data];
}
return self;
}
/**
* 初始化數(shù)據(jù)源
*/
-(NSMutableArray *)createTempData : (NSArray *)data{
NSMutableArray *tempArray = [NSMutableArray array];
for (int i=0; i<data.count; i++) {
Node *node = [_data objectAtIndex:i];
if (node.expand) {
[tempArray addObject:node];
}
}
return tempArray;
}
#pragma mark - UITableViewDataSource
#pragma mark - Required
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _tempData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *NODE_CELL_ID = @"node_cell_id";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NODE_CELL_ID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NODE_CELL_ID];
}
Node *node = [_tempData objectAtIndex:indexPath.row];
NSMutableString *name = [NSMutableString string];
for (int i=0; i<node.depth; i++) {
[name appendString:@" ? ? "];
}
[name appendString:node.name];
cell.textLabel.text = name;
return cell;
}
#pragma mark - Optional
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 0.01;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 40;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 0.01;
}
#pragma mark - UITableViewDelegate
#pragma mark - Optional
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//先修改數(shù)據(jù)源
Node *parentNode = [_tempData objectAtIndex:indexPath.row];
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;
}else{
expand = NO;
endPosition = [self removeAllNodesAtParentNode:parentNode];
break;
}
endPosition++;
}
}
//獲得需要修正的indexPath
NSMutableArray *indexPathArray = [NSMutableArray array];
for (NSUInteger i=startPosition; i<endPosition; i++) {
NSIndexPath *tempIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPathArray addObject:tempIndexPath];
}
//插入或者刪除相關(guān)節(jié)點
if (expand) {
[self insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
}else{
[self deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
}
}
/**
* ?刪除該父節(jié)點下的所有子節(jié)點(包括孫子節(jié)點)
*
* ?@param parentNode 父節(jié)點
*
* ?@return 鄰接父節(jié)點的位置距離該父節(jié)點的長度,也就是該父節(jié)點下面所有的子孫節(jié)點的數(shù)量
*/
-(NSUInteger)removeAllNodesAtParentNode : (Node *)parentNode{
NSUInteger startPosition = [_tempData indexOfObject:parentNode];
NSUInteger endPosition = startPosition;
for (NSUInteger i=startPosition+1; i<_tempData.count; i++) {
Node *node = [_tempData objectAtIndex:i];
endPosition++;
if (node.depth == parentNode.depth) {
break;
}
node.expand = NO;
}
if (endPosition>startPosition) {
[_tempData removeObjectsInRange:NSMakeRange(startPosition+1, endPosition-startPosition-1)];
}
return endPosition;
}
<br/>
四、總結(jié)
在演示項目中,每個cell我都使用系統(tǒng)自帶的cell,樣式比較簡單,如果你要展現(xiàn)更加漂亮的樣式,可以自定義cell。<br/>
同時,你也可以擴展該數(shù)據(jù)模型,運動到更加復(fù)雜的業(yè)務(wù)處理中。比如以下場景:
這里寫圖片描述
<br/>
五、下載地址
github下載地址:https://github.com/yixiangboy/TreeTableView<br/>
========
使用UITableView實現(xiàn)樹視圖
http://blog.csdn.net/kmyhy/article/details/5753090 《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的IOS树视图学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: powertool 使用学习总结
- 下一篇: Linux下的ELF可执行文件学习总结