前面幾篇文章記錄了UITableView的一些特性和使用,今天突然想要寫一篇關於UITableView的個人理解。
UITableView是一個列表控件,但是在開發中,列表的樣子是千奇百怪。每個產品都希望自己設計的app界面是獨一的,有這自己的元素。比如:微信的朋友圈列表(動態高度),QQ好友列表(點擊展示隱藏分組),京東的物品分類列表(瀑布流)等等。。。
面對這樣複雜多變的設計,作爲一個開發人員,要有自己的一套對於界面的理解,也就是對於控件的理解,這裏我就以QQ好友列表爲例簡單說一下我對於複雜列表界面的開發思路。
下面是代碼,在代碼中有必要的註釋。
#import "ViewController.h"
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
{
UITableView *table;
//用於列表展示的數據源
NSMutableArray *dataSource;
//保存列表數據的數據源
NSMutableArray *data;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createDataSource];
[self createTableView];
}
//s初始化數據源
- (void)createDataSource{
NSArray *array = @[@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"],
@[@"111",@"222",@"333",@"444",@"555",@"666",@"777"]];
data = [NSMutableArray arrayWithArray:array];
dataSource = [NSMutableArray arrayWithCapacity:0];
for (int i=0; i<10; i++) {
NSDictionary *dic = @{@"isOpen":@"open", @"data":@[]};
[dataSource addObject:dic];
}
}
//創建視圖
- (void)createTableView{
//創建並設置位置大小和風格形式
//由於QQ分組在展開分組好友滾動時有組頭定位,也就是在下一個組頭滾動到tableView的最上方時當前的組頭一直在最上方位置,所以即使是分組的列表,UITableView的style也還是UITableViewStylePlain
table = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
//設置代理
table.delegate = self;
table.dataSource = self;
//設置縱橫滑塊不顯示
table.showsVerticalScrollIndicator = NO;
table.showsHorizontalScrollIndicator = NO;
[self.view addSubview:table];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return dataSource.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSDictionary *dic = dataSource[section];
NSArray *array = [dic objectForKey:@"data"];
return array.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 40;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 30;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 0.01;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
//設置分組的頭視圖
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)];
view.backgroundColor = [UIColor yellowColor];
view.tag = section;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 100, 20)];
label.text = [NSString stringWithFormat:@"第%ld組",section];
label.userInteractionEnabled = YES;
[view addSubview:label];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(headClick:)];
[view addGestureRecognizer:tap];
return view;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
return nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
NSDictionary *dic = dataSource[indexPath.section];
NSArray *array = [dic objectForKey:@"data"];
cell.textLabel.text = array[indexPath.row];
return cell;
}
- (void)headClick:(UITapGestureRecognizer *)tap{
UIView *view = tap.view;
NSInteger section = view.tag;
NSDictionary *dic = dataSource[section];
NSString *isOpen = [NSString stringWithFormat:@"%@",[dic objectForKey:@"isOpen"]];;
BOOL ok = [isOpen isEqualToString:@"open"];
if (ok) {
[dataSource removeObjectAtIndex:section];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:0];
NSArray *array = data[section];
[dict setObject:@"close" forKey:@"isOpen"];
[dict setObject:array forKey:@"data"];
[dataSource insertObject:dict atIndex:section];
}else{
[dataSource removeObjectAtIndex:section];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:0];
NSArray *array = @[];
[dict setObject:@"open" forKey:@"isOpen"];
[dict setObject:array forKey:@"data"];
[dataSource insertObject:dict atIndex:section];
}
[table reloadData];
}
@end
由於是寫一個例子,所以沒有去自定義cell,沒有做數據model。只是簡單實現需求。在上面的代碼實例中可以看到,對於列表的展示和隱藏我是通過控制數據源實現的。通過數據源的變化再刷新視圖。
總結:UITableView是一個列表視圖,對於列表視圖有一個很重要的特點就是它的展示和數據源有很大的關係,比如列表的多少,比如列表的展示風格等等。這些特性就是我們開發複雜界面的關鍵,對於列表的設計在很多時候可以通過改動數據源實現。就像上面的例子一樣,通過點擊修改數據源中對應分組中的數據來實現每組中cell的個數,從而實現展示和隱藏。
同樣的對於微信的朋友圈列表,也是通過改變數據源的數據進行的,當評論時數據源發生變化,獲取到新的數據源後刷新界面。
雖然UITableView是一個視圖控件,但是對於它的操作並不是簡單的使用屬性之類的設置,面對複雜多變的設計,靈活運用數據源纔是最簡單的方法。這一點不僅僅是在UITableView的使用上,在很多地方都是一樣的,一個app的開發,界面不管有多少,無非就是一些控件的組合,真正多變的是數據,對於數據的處理纔是重點。
(上面是一些本人的個人理解,不喜勿噴)