UITable View实例教程:分组显示列表

2009年6月18日 | laifangwen

UITableView - Sectioned Table View
UITable View—分组列表视图

Introduction
本章介绍

So far we have seen how easy it is to display list of items in a table view. As it turns out, displaying grouped items is easy too. This is the third tutorial in the UITableView tutorial series and it borrows its source code from the previous one. This is how the final app will look like
通过前面的学习,可以看到在table view视图上显示条目列表是一件很容易的事。事实证明,分组显示条目列表也是很容易的。这是UITableView系列教程的第三篇,在本篇教程中,仍然借用之前的代码并在其基础上学习。最后的界面如下图所示:
 

Preparing the Data Source
准备数据源

From the above picture it is obvious that the countries are grouped into two sections: "Countries to visit" and "Countries visited". I don't know where I want to go next but Iceland is been on my list for a long time :).
从上面的图片中很容易看出,国家列表被分成两部分:"Countries to visit" 和"Countries visited"。我不知道下次我想访问那个国家,但Iceland在我行程计划里已经很久了:)。

Since the information is now grouped, we need to create our data source in a specific way, which will make it easier to display the data. We will still use a NSMutableArray to hold the data. This time we will populate it with two dictionary objects, instead of simple strings. The dictionary objects will contain one key/value pair, where the key will be a string and the value will be an array containing all the countries. This is done in viewDidLoad method and this is how the method changes from the second tutorial
由于那些信息分组,为使得更容易和view视图相结合显示,我们需要创建一个特殊的数据源。仍然创建NSMutableArray类型的数据。这次用两个dictionary objects来代替之前用的简单的字符串来填充listOfItems。dictionary objects包含key和对应的value。在我们的例子中,key为一个字符串,value为一组国家名称。在viewDidLoad方法中完成数据的初始化,实现的代码如下:


//RootViewController.m
- (void)viewDidLoad {
[super viewDidLoad];

//Initialize the array. 初始化listOfItems对象
listOfItems = [[NSMutableArray alloc] init];

NSArray *countriesToLiveInArray = [NSArray arrayWithObjects:@"Iceland", @"Greenland", @"Switzerland", @"Norway", @"New Zealand", @"Greece", @"Rome", @"Ireland", nil];
NSDictionary *countriesToLiveInDict = [NSDictionary dictionaryWithObject:countriesToLiveInArray forKey:@"Countries"];

NSArray *countriesLivedInArray = [NSArray arrayWithObjects:@"India", @"U.S.A", nil];
NSDictionary *countriesLivedInDict = [NSDictionary dictionaryWithObject:countriesLivedInArray forKey:@"Countries"];

[listOfItems addObject:countriesToLiveInDict];
[listOfItems addObject:countriesLivedInDict];

//Set the title 设置导航条标题
self.navigationItem.title = @"Countries";
}

P.S The array is declared in the header file and released in the dealloc method, this is shown in the first part of the tutorial. It also contains information about the detail view.

We create two arrays: countries to visit and countries visited. The arrays are then used to create dictionary objects with the key "Countries" and they are added to the "listOfItems" array with countries to live followed by countries lived in.
备注:在第一篇教程中,listOfItems是已经在头文件中声明并在dealloc释放,同时包含有细节视图。
在上面代码中,我们创建了两个数组:countries to visit和countries visited。数组被应用到dictionary objects对象中,key设置为"Countries"。最后dictionary objects被添加到listOfItems对象中。


Preparing UITableView to display data
在UITableView视图中显示数据

The table view needs to know how many sections it should expect, which is the number returned in numberOfSectionsInTableView method. Since we only have two dictionary objects added to the array, it know to display two sections. This is how the code looks like
在让table view显示时,我们需要告诉table view有几部分数据将要显示。我们用numberOfSectionsInTableView 方法来实现,该方法返回一个数值,可以告知table view分为几个section。在我们的例子中,我们添加了两个dictionary对象给列表对象,因此意味着我们要分两个section来显示。下面的代码可以完成这件事情:


//RootViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

return [listOfItems count];
}

The table view needs to know how many rows it should expect it in every section, which is the number returned in tableView:numberOfRowsInSection method. This is how the code looks like
此外,table view需要知道在每个sectiong中,有多少行需要显示。这可以用tableView:numberOfRowsInSection 方法来实现。实现的代码如下:


//RootViewController.m
// Customize the number of rows in the table view.自定义table view的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

//Number of rows it should expect should be based on the section 基于每个section定义需要显示的行数
NSDictionary *dictionary = [listOfItems objectAtIndex:section];
NSArray *array = [dictionary objectForKey:@"Countries"];
return [array count];
}

We have added two dictionary objects in the array, so this method will be called twice. Since the index of the section and the array starts with 0, We can use this to get the dictionary located at a specific index. Once we find out which dictionary the table view is displaying, we get the array using the key "Countries" and return the count of the array.
说明:已经在列表对象中添加了两个array类型的对象,所以上面的程序会调用两次。一般的sevction对象和数组的索引都是以0开始的,我们用的是一个特殊的索引。当dictionary对象在table view显示时,我们获取他的数组用"Countries"作为索引,同时返回数组包含对象的总数。

Displaying the header text
显示section的标题

We took care of the number of sections and the rows the table view should know about. We still have to display the actual header text that shows up in the table view. This is done in tableView:titleForHeaderInSection method which is called twice since we only have two groups. This is how the code looks like
我们已经显示所有的section条目在我们的table view中,但整体看起来好像一个列表,而我们的目的要让条目列表分为几个section来显示。所以需要给每个section添加一个标题来区分。我们通过tableView:titleForHeaderInSection 方法来实现,由于我们仅定义了两个section,所以会调用了两次。实现的代码如下所示:


//RootViewController.m
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

if(section == 0)
return @"Countries to visit";
else
return @"Countries visited";
}

We know that the first dictionary in "listOfItems" array contains the list of countries I want to visit. So the above code checks if the section is 0 or not and displays the relevant header text.
在"listOfItems"中,第一个section我们定义的是我们想要访问的国家列表,所以上面的代码中首先检查是否是第一个section,即索引为0的section,如果是第一个secion则显示Countries to visit标题,否则显示另外一个标题。

Displaying the text of the UITableViewCell

在UITableViewCell里显示内容
We now have the header text but what about the text of the cell. The logic is similar to that of tableView:numberOfRowsInSection. We first find out which dictionary object we should read, from the section property of NSIndexPath. We then get the dictionary object, with its array from the key "Countries". At last we display the text of the cell by getting the string at a given row, which comes from the row property of NSIndexPath. This is how the code looks like
我们已经定义两个section和对应的section的标题,但还需要在table view中给出对应的cell来显示。使用tableView:numberOfRowsInSection方法来定义。首先用section的索引来查找需要读取的section对象。通过使用定义的key"Countries"获取section里的dictionary object的数组。最后通过NSIndexPath属性显示在已经定义的cell里。最后的代码如下:


//RootViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}

// Set up the cell...

//First get the dictionary object
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:@"Countries"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.text = cellValue;

return cell;
}

Selecting the right row
条目选择方法

The method tableView:didSelectRowAtIndexPath also changes, to adjust the sectioned table view. This is how the code looks like
为适合分组的table view,tableView:didSelectRowAtIndexPath方法也需要进行相应的变化。现在的代码如下:


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

//Get the selected country

NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:@"Countries"];
NSString *selectedCountry = [array objectAtIndex:indexPath.row];

//Initialize the detail view controller and display it.
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
dvController.selectedCountry = selectedCountry;
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}

The code is similar to tableView:cellForRowAtIndexPath, in how we access the dictionary, array, and the selected country value.
上面的代码和tableView:cellForRowAtIndexPath方法很像,在选择section里的条目并显示。
Run your application to see the sectioned table view in action.

Setting the style of UITableView
设置UITableView的外观

If your app looks like the picture above, then the style of the table view is set to "Plan" in Interface Builder. Change this to "Grouped" and see how the display changes when you run the app.
如果你的程序看起来和前面的图片一样,在Interface Builder里设置table view的样式的"Plan",改为"Grouped"。运行程序,看看有什么变化。

Conclusion
结论

We have seen how we can display some information which is grouped together. I hope this tutorial was helpful to you and please leave your comments. My next tutorial will show you how to search the UITableView using the UISearchBar control.
我们已经学习了分组展示信息列表,希望对你有帮助。有用的同时不要忘了留下你的评论。下一篇学习在table view中搜索。

翻译:http://blog.laifangwen.com  译文:http://blog.laifangwen.com/htmldata/iPhone/2009/06/18/222.html

作者:http://www.iphonesdkarticles.com  英文:http://www.iphonesdkarticles.com/2009/01/uitableview-sectioned-table-view.html

Happy Programming,
iPhone SDK Articles

原创翻译,欢迎转载,但需保留作者信息和翻译者信息,谢谢!

本例UITableView源码下载:

TableViewPart3.zip

Tags: UITableView  iPhone  实例  object-c  
相关文章:

UITableView实例教程:创建Table View的detail view  (2009-6-16 17:32:57)

UITableView使用实例:创建一个简单的Table View  (2009-6-16 11:40:59)

引用通告地址: http://blog.laifangwen.com/cmd.asp?act=gettburl&id=222

评论: 0 | 引用: 0 | 浏览:
名称(*):
邮箱:
网站链接:
正文(*):
选 项:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。