UITableView 表格視圖
一 UITableView
1.1是什么?
以列表的方式展示數據的一種控件,且繼承自UISrollView,默認是只能上下滾動;
1.2 使用步驟:
1)創建UITableView對象,并設置樣式;
2)配置要展示的數據和外觀;
三問:
1)有幾個分區?
2)每個分區有多少行?
3)每行的展示的內容是什么?
3)把它添加到父視圖上顯示;
見【Demo】-【1-UITableView】
-
(void)viewDidLoad {
[super viewDidLoad];self.automaticallyAdjustsScrollViewInsets = NO;(消除導航控制器對其的影響)
/********** 創建UITableView ************/
//UITableViewStylePlain 普通平板樣式
//UITableViewStyleGrouped 分組樣式
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStylePlain];myTableView.delegate = self;
myTableView.dataSource = self;[self.view addSubview:myTableView];
}
pragma mark -UITableViewDataSource
//三問 【** 重點 **】
//1問,告訴tableView應該顯示多少個分區【如果不實現,默認是1個分區】
-
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
//2問,告訴tableView每個分區顯示多少行 (該方法有幾個分區調用幾次)
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.dataArray count];
}
//3問,告訴tableView每一行顯示的具體內容是什么
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//創建靜態的標識
static NSString *cellID = @"MyCell";
//先從tableView的復用池中去查找沒有帶cellID標識的單元格;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//如果沒有找到(復用池中沒有符合條件的單元格)
if (cell == nil) {
//自己創建一個新的單元格,并初始化單元格的樣式,給它加上標識
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}
//什么是indexPath?indexPath.row?
MyModel *model = self.dataArray[indexPath.row];
cell.textLabel.text = model.title;//返回符合條件的單元格對象;
return cell;
}
1.3 cell簡介 【重點】
UITableView的每一行都是一個UITableViewCell類型的對象,通過dataSource的第三問來初始化每一行;
【cell 的復用機制】
當滾動列表時候,部分UITableViewCell會移出窗口;UITableView會將移出去的UITableViewCell放入到一個復用池中,等待重用,當UITableView要求返回UITableViewCell的時候,會先查看復用池,如果池中有未使用的病符合條件的UITableViewCell,就會直接拿來使用,并重新配置這個UITableViewCell展示的內容,然后返回給UITableView,如果池子中沒有符合條件的cell,那么則創建一個新的UITableViewCell對象,并返回!
cell的復用機制保證了值創建有限個cell的對象,來顯示無限條數據,極大限度的節約了內存的開銷,提高了性能,具有極大的借鑒意義;
1.4 UITableView的原理
a 先詢問有幾個分區
b 根據分區的個數,再多次詢問每個分區有多少行,每次詢問的時候,會攜帶分區的section;
c 根據分區號及分區內的行號,再多次詢問每一行顯示的內容是什么,其中分區號section和行號row會組成一個NSIndexPath的類型,作為參數傳遞給方法;
-
(void)viewDidLoad {
[super viewDidLoad];//1.請求數據
[self reloadData];
//2.創建UITableView
[self creatUITableView];
}
-(void)creatUITableView
{
self.automaticallyAdjustsScrollViewInsets = NO;//添加背景圖片
UIImageView *bgImg = [[UIImageView alloc] initWithFrame:screenBounds];
bgImg.image = [UIImage imageNamed:@"5.jpg"];
// [self.view addSubview:bgImg];UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStyleGrouped];
//必寫
myTableView.delegate = self;
myTableView.dataSource = self;
// myTableView.backgroundColor = [UIColor clearColor];
myTableView.backgroundView = bgImg;UIImageView *headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
headerView.image = [UIImage imageNamed:@"10.jpg"];
headerView.contentMode = UIViewContentModeScaleAspectFit;
UIImageView *footerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
footerView.image = [UIImage imageNamed:@"15.jpg"];
footerView.contentMode = UIViewContentModeScaleAspectFit;
//給myTableView設置頭部視圖
myTableView.tableHeaderView = headerView;
//給myTableView設置尾部視圖
myTableView.tableFooterView = footerView;[self.view addSubview:myTableView];
}
pragma mark -UITableViewDataSource
//3問 每行顯示的內容是什么
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"cellName";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
//系統給我們提供了3中Cell樣式
// UITableViewCellStyleDefault,
// UITableViewCellStyleValue1,
// UITableViewCellStyleValue2,
// UITableViewCellStyleSubtitle
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//將數據源中的數據,賦值給cell對象展示出來
UserModel *model = self.dataArray[indexPath.section][indexPath.row];
//1.顯示主標題
cell.textLabel.text = model.name;
//2.設置頭像
cell.imageView.image = [UIImage imageNamed:model.iconImage];//設置圓角
cell.imageView.layer.cornerRadius = 8;
cell.imageView.layer.masksToBounds = YES;
// cell.imageView.layer.borderColor = (__bridge CGColorRef)([UIColor redColor]);
// cell.imageView.layer.borderWidth = 10;//3.顯示副標題
cell.detailTextLabel.text = model.detailTitle;//設置cell右側的提示樣式
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor clearColor];return cell;
}
/**************************** 相關屬性 *******************************/
//設置分區cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
//設置分區的頭部視圖的標題
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c區的頭部標題",(char)('A'+section)];
}
//設置分區的尾部標題
-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c區的尾部標題",(char)('A'+section)];
}
/****************** 自定義分區的頭部,尾部視圖 **********************/
//當同時設置分區的頭部標題和頭部視圖,那么優先顯示頭部視圖
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c區的頭部標題",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:20];
label.backgroundColor = [UIColor cyanColor];
label.textColor = [UIColor redColor];
return label;
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c區的尾部標題",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:15];
label.backgroundColor = [UIColor magentaColor];
label.textColor = [UIColor yellowColor];
return label;
}
/********************* 設置分區的頭部視圖的高度 ****************/
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 100;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 50;
}
//設置右邊索引
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *mArr = [NSMutableArray array];
for (int i='A'; i<='Z'; i++) {
NSString *str = [NSString stringWithFormat:@"%c",i];
[mArr addObject:str];
}
return mArr;
}
1.5 UITableViewController 表格視圖控制器
UIViewController 管理視圖的
UINavigationController 管理多個UIViewController
UITabBarController 即可以管理導航控制器,也可以管理UIViewController
2.1 概念
UITableViewController管理的是一個UITableView;
為了配合UITableView的使用而專門設立的一種特殊控制器,專門用來管理表格視圖;
2.2 特點:
1)繼承自UIViewController
2)自帶的視圖已經是UITableView類型,通過 .tableView的屬性來訪問自己攜帶的表格視圖;
3)控制器本身已經默認遵守了UITableViewDelegate和UITableViewDataSource,并且設置了自己作為該表格式圖的代理對象;
4)創建一個表格式圖控制器類,繼承自UITableViewController,在這個類中專心處理相關代理方法【最主要的三問】;
見【Demo】-【3-UITableViewController】
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//從表格視圖的復用池中按照之前注冊指定的標識去取可重用的對象;
//該方法一定會返回一個不為nil的對象;
//因為:復用池中如果沒有可重用的單元格,系統會根據之前注冊的類,自動的創建一個單元格對象并返回;
//如果復用池中有可重用的單元格,系統會直接返回;
//優點:自動處理一切細節,減少代碼量;
//缺點:這種形式返回的cell對象,只能是默認的樣式,其他的三種樣式無法設置;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];//取出數據源中對應的數據模型,并展示在cell上
StudentModel *model = self.dataArray[indexPath.section][indexPath.row];
cell.textLabel.text = model.name;
cell.imageView.image = [UIImage imageNamed:model.icon];cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
pragma mark -UITableViewDelegate
//一答 【** 重點 **】
//當選中cell的時候,調用該方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//拿到當前點擊的cell所對應的數據模型
StudentModel *model = self.dataArray[indexPath.section][indexPath.row];
//跳轉到詳情頁面
DeatilViewController *dvc = [[DeatilViewController alloc] initWithNibName:@"DeatilViewController" bundle:nil];
//把這個model屬性傳值給詳情頁面
dvc.model = model;
__block MyTableViewController *weakself = self;
dvc.block = ^{
//刷新當前的tableView(系統自帶的方法)
[weakself.tableView reloadData];
};
[self.navigationController pushViewController:dvc animated:YES];
}
關于單元格的實現方法:
方式一:
1)定義靜態標識
2)根據標識從復用池中取對象
3)如果有,重新賦值后,直接使用
4)如果沒有,那么新建一個單元格
方法二:
1)在viewDidLoad中,提前注冊號單元格,并指定標識
2)在第三問時,直接從復用池中取,就算沒有可重用的單元格,系統內部會根據一早注冊號的單元格樣式創建單元格,并返回,如果有可重用的,直接返回;
《但方法二生成的單元格樣式只能是默認樣式,其他樣式無法設置》
兩種設置cell顯示內容的方式: 【** 重點 **】
第一種:
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//創建靜態的標識
static NSString *cellID = @"MyCell";
//先從tableView的復用池中去查找沒有帶cellID標識的單元格;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//如果沒有找到(復用池中沒有符合條件的單元格)
if (cell == nil) {
//自己創建一個新的單元格,并初始化單元格的樣式,給它加上標識
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}
//什么是indexPath?indexPath.row?
MyModel *model = self.dataArray[indexPath.row];
cell.textLabel.text = model.title;//返回符合條件的單元格對象;
return cell;
}
第二種:
//提前注冊cell
[cView registerClass:[MyCell class] forCellWithReuseIdentifier:@"Cell"];
//3問 每一項顯示什么內容
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//從復用池中取有沒有符合要求的單元格,如果有,直接返回使用,如果沒有,系統會根據之前注冊的單元格,自動的創建一個單元格對象,并返回;
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
//因為UICollectionViewCell是系統自帶的cell,所以沒有提供樣式,沒有提供對應的空間,只能設置相關屬性;
cell.model = self.dataArray[indexPath.section][indexPath.row];
cell.backgroundColor = [UIColor orangeColor];
return cell;
}
如果cell用xib寫的話,提前注冊用下面這種寫法:
[self.tableView registerNib:[UINib nibWithNibName:@"AppCell" bundle:nil] forCellReuseIdentifier:@"AppCellID"];
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AppCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AppCellID" forIndexPath:indexPath];cell.model = self.dataArray[indexPath.row];
return cell;
}