您的位置:首页 > 产品设计 > UI/UE

iOS开发 自定义tableView样式(使用代码/使用Interface Builder)、分组显示、给TableView增加索引、给TableView增加SearchBar

2013-01-10 16:42 786 查看


1、使用代码

自定义tableView样式有两种方法,一种是用代码写cell的subView,另一种是导入nib文件(就是用Interface Builder设计),这篇笔记记录的是代码的方法.

1、新建一个Single View Application 项目,如前文,只选Use Automatic Reference Counting.

2、打开PDViewController.xib,拖进一个Table View,选中Table View,打开Connections inspector,拖动delegate和dataSource右边的小圆到File’s Owner.

3、新建文件,选Cocoa Touch—-Objective-C class,输入类名,我这是MyCell,Subclass of UItableViewCell.生成MyCell.h和MyCell.m两文件。

MyCell.h:

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface MyCell : UITableViewCell

@property (copy,nonatomic) NSString *name;

@property (copy,nonatomic) NSString *color;

@end

MyCell.m:

[cpp] view
plaincopy

#import "MyCell.h"

#define kNameTag 1

#define kColorTag 2

@implementation MyCell

@synthesize name=_name,color=_color;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

if (self) {

// Initialization code

CGRect nameLableRect=CGRectMake(0, 5, 100, 15);

//定义一个距形,位置0,5,宽100高15,就是绝对定位

UILabel *nameLable=[[UILabel alloc] initWithFrame:nameLableRect];

//在距形定义的位置实例化一个UILable对象

nameLable.tag=kNameTag;

[self.contentView addSubview:nameLable];

CGRect colorLableRect=CGRectMake(0, 30, 100, 15);

//定义一个距形,距离上面的nameLable 10

UILabel *colorLable=[[UILabel alloc] initWithFrame:colorLableRect];

//在距形定义的位置实例化一个UILable对象

colorLable.tag=kColorTag;

[self.contentView addSubview:colorLable];

}

return self;

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated

{

[super setSelected:selected animated:animated];

// Configure the view for the selected state

}

//自己写name和color的setter方法

-(void)setName:(NSString *)name

{

if(![name isEqualToString:_name])

{

_name=[name copy];

UILabel * nameLable=(UILabel *)[self.contentView viewWithTag:kNameTag];

//通过viewWithTag方法得到UILable

nameLable.text=_name;

}

}

-(void)setColor:(NSString *)color

{

if(![color isEqualToString:_color])

{

_color=[color copy];

UILabel * colorLable=(UILabel *)[self.contentView viewWithTag:kColorTag];

colorLable.text=_color;

}

}

@end

PDViewControllor.h:

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface PDViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>

//简单起见,不再定义数据,每行数据都一样

@end

PDViewController.m

[cpp] view
plaincopy

#import "PDViewController.h"

#import "MyCell.h"

@implementation PDViewController

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}

#pragma mark - View lifecycle

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

}

- (void)viewDidUnload

{

[super viewDidUnload];

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

}

- (void)viewDidAppear:(BOOL)animated

{

[super viewDidAppear:animated];

}

- (void)viewWillDisappear:(BOOL)animated

{

[super viewWillDisappear:animated];

}

- (void)viewDidDisappear:(BOOL)animated

{

[super viewDidDisappear:animated];

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

// Return YES for supported orientations

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

return 100;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString * tableIdentifier=@"Custom table";

MyCell *cell=[tableView dequeueReusableCellWithIdentifier:tableIdentifier];

if(cell==nil)

{

cell=[[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];

}

cell.name=@"标题";

cell.color=@"颜色";

//不再定义数据,每行都一样

return cell;

}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

return 60;

}

@end

转自http://www.pocketdigi.com/20120227/678.html


2、使用Interface
Builder

前面说到用代码写TableViewCell的样式(),但代码必竟没有Interface
Builder来得方便,今天就介绍使用Interface Builder编辑NIB文件来实现自定义样式。

前面两步与用代码相同,即:

1、新建一个Single View Application 项目,如前文,只选Use Automatic Reference Counting.

2、打开PDViewController.xib,拖进一个Table View,选中Table View,打开Connections inspector,拖动delegate和dataSource右边的小圆到File’s Owner.

第3步,也是写一个继承自UItableViewCell的类(我这取名NIBCell),但内容稍有不同。

NIBCell.h:

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface NIBCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UIImageView *thumbView;

@property (strong, nonatomic) IBOutlet UILabel *titleView;

//两个outlet与NIB文件中的控件连接

@property (copy,nonatomic) NSString * title;

@property (strong,nonatomic) UIImage * thumb;

//两个属性分别用于设置上面两个outlet的属性

@end

NIBCell.m

[cpp] view
plaincopy

#import "NIBCell.h"

@implementation NIBCell

@synthesize thumbView = _thumbView;

@synthesize titleView = _titleView;

@synthesize title=_title,thumb=_thumb;

/*

因为样式是在nib文件中定义的,所以不再需要

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 方法

*/

- (void)setSelected:(BOOL)selected animated:(BOOL)animated

{

[super setSelected:selected animated:animated];

// Configure the view for the selected state

}

-(void)setTitle:(NSString *)title

{//覆盖默认生成的setter,但有outlet,不再需要content的viewWithTag方法来取得View

if(![self.title isEqualToString:title])

{

_title=title;

_titleView.text=_title;

}

}

-(void)setThumb:(UIImage *)thumb

{

if(![self.thumb isEqual:thumb])

{

_thumb=thumb;

[_thumbView setImage:_thumb];

}

}

@end

第四步,新建文件,IOS–User Interface–Empty,我这取名TableViewCell.xib

5、单击TableViewCell.xib以便用Interface Builder打开编辑(这时是空的),从控件库里找到Table View Cell,拖进Interface Builder,再拖进一个UILable,和一个UIImage View用于显示一段文字和图片(与前面NIBCell类中的定义相符)

6、选中整个Table View Cell,打开Identity Inspector,把Class改为NIBCell。

7、打开Connections Inspector,找到两个Outlet,thumbView和titleView(我们在NIBCell中定义的),将其右边的小圆圈拖动到Interface Builder里相应的UIImage View和 UILable控件上,建立连接。

8、PDViewController代码:

PDViewController.h

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface PDViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>

//与前面相同,为了简便,不定义用于存储每行信息的数组

@end

PDViewController.m

[cpp] view
plaincopy

#import "PDViewController.h"

#import "NIBCell.h"

@implementation PDViewController

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}

#pragma mark - View lifecycle

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

}

- (void)viewDidUnload

{

[super viewDidUnload];

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}

- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

}

- (void)viewDidAppear:(BOOL)animated

{

[super viewDidAppear:animated];

}

- (void)viewWillDisappear:(BOOL)animated

{

[super viewWillDisappear:animated];

}

- (void)viewDidDisappear:(BOOL)animated

{

[super viewDidDisappear:animated];

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

// Return YES for supported orientations

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

//返回行数

return 100;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString * tableIdentifier=@"CellFromNib";

static BOOL nibsRegistered=NO;

if(!nibsRegistered)

{//第一次运行时注册nib文件,文件名不需要扩展名

UINib *nib=[UINib nibWithNibName:@"TableViewCell" bundle:nil];

[tableView registerNib:nib forCellReuseIdentifier:tableIdentifier];

nibsRegistered=YES;

}

NIBCell *cell=[tableView dequeueReusableCellWithIdentifier:tableIdentifier];

NSUInteger rowNumber=[indexPath row];

NSString *title=[[NSString alloc] initWithFormat:@"%d",rowNumber];

cell.title=title;

UIImage *image=[UIImage imageNamed:@"57"];

cell.thumb=image;

//显示行号,和一张固定的图片,图片同样不需要扩展名

return cell;

}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

//返回行高

return 100;

}

@end

转自http://www.pocketdigi.com/20120319/713.html


3、分组显示TableView

IOS中可以分组显示TableView,效果类似于“设置”程序。

新建项目的步骤不再重复,请参考前文。有一点区别在于,需要把Table View的Style属性设置成Grouped(在Attributes Inspector中)。这里需要先写个plist文件,用于存储需要显示的数据。

plist文件本身对应NSDictionary数据类型,也就是说plist文件,其实是个字典。本例plist文件名为sortednames.plist,内容及结构如下图:



两个字符串数组,键名分别为A,B,当然,你也可以在程序中用代码写NSDictionary,这样就不需要sortednames.plist。

PDViewController.h

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface PDViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>

@property (strong,nonatomic) NSDictionary *names;

@property(strong,nonatomic)NSArray *keys;

@end

PDAppDelegate.m

[cpp] view
plaincopy

#import "PDViewController.h"

#import "NIBCell.h"

@implementation PDViewController

@synthesize names=_names,keys=_keys;

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}

#pragma mark - View lifecycle

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

NSString *path=[[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];

//取得sortednames.plist绝对路径

//sortednames.plist本身是一个NSDictionary,以键-值的形式存储字符串数组

NSDictionary *dict=[[NSDictionary alloc] initWithContentsOfFile:path];

//转换成NSDictionary对象

self.names=dict;

NSArray *array=[[_names allKeys] sortedArrayUsingSelector:@selector(compare:)];

//取得字典中所有的key,使用compare方法(必须是返回NSComparisonResult的方法)排序

//这里取得的key,对应的值是Array

_keys=array;

}

- (void)viewDidUnload

{

[super viewDidUnload];

self.names=nil;

self.keys=nil;

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

// Return YES for supported orientations

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

//返回分组数量,即Array的数量

return [_keys count];

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

//返回第section个分组的行数

NSString *key=[_keys objectAtIndex:section];

//取得key

NSArray *nameSection=[_names objectForKey:key];

//根据key,取得Array

return [nameSection count];

//返回Array的大小

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

NSUInteger section=[indexPath section];

//分组号

NSUInteger rowNumber=[indexPath row];

//行号

//即返回第section组,rowNumber行的UITableViewCell

NSString *key=[_keys objectAtIndex:section];

//取得第section组array的key

NSArray *nameSection=[_names objectForKey:key];

//通过key,取得Array

static NSString * tableIdentifier=@"CellFromNib";

UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:tableIdentifier];

if(cell==nil)

{

cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];

}

cell.textLabel.text=[nameSection objectAtIndex:rowNumber];

//从数组中读取字符串,设置text

return cell;

}

@end

转自http://www.pocketdigi.com/20120320/715.html

4、给TableView增加索引

当TableView显示的数据很多的时间,可以给其添加索引,添加索引后,在TableView的右侧会显示索引的键,手指滑动这里,就可以快速切换到该键对应的数据(好像联系人就是这样的,很久没用iPhone了,不敢肯定,我只有iPod,没联系人).

具体实现代码只需在前文的基础上修改。

打开PDViewController.m,增加一个selector:

[cpp] view
plaincopy

-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

{

return _keys;

//通过key来索引

}

上面的这个selector是在UITableViewDataSource中声明的,我们已经支持了这个协议。

Table View的Style属性,不管是默认的Plain还是前文中修改的Grouped都可以。

转自http://www.pocketdigi.com/20120321/719.html


5、给TableView增加SearchBar



可以根据输入的关键字,在TableView中显示符合的数据。

图中分组显示和索引效果,前面的博文已经记录,不再赘述。下面的例子是基于前文的基础上修改的,所以文件名啥的,请参考前文。

第一步是在TableView上方添加一个Search Bar,这里有一点需要注意,必须先把TableView拖下来,留下空间放Search Bar,不要在Table View占满屏幕的情况下把Search Bar拖到Table View顶部。区别在于,使用后面的方法,Search
Bar是作为Table View的Header部分添加的,而前面的方法,Search Bar是独立的。在添加索引功能时,如果作为Table View的Header添加,右侧的索引会遮住Search Bar的右边部分。Search Bar几个常用属性:

Placeholder是提示,就是hint属性,Corretion是自动修正,一般设为NO,即不修正,Show Cancel Button是显示取消按钮,我这里勾选。选中Search Bar的情况下切换到Connections Inspector面板,delegate与File’s
Owner建立连接(我们会在ViewController中支持UISearchBarDelegate协议)。与前面几篇文章的例子相同,ViewController文件名为PDViewController.h和PDViewController.m。

第二步,添加Table View和Search Bar的Outlet.按住Control键,分别拖动Table View和Search Bar到PDViewController.h,添加Outlet

第三步,就是PDViewController代码:

PDViewController.h:

[cpp] view
plaincopy

#import <UIKit/UIKit.h>

@interface PDViewController : UIViewController<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate>

@property (strong,nonatomic) NSDictionary *names;

@property (strong,nonatomic) NSMutableDictionary *mutableNames;

@property (strong,nonatomic)NSMutableArray *mutableKeys;

//可变字典和可变数组,用于存储显示的数据,而不可变的字典用于存储从文件中读取的数据

@property (strong, nonatomic) IBOutlet UITableView *table;

@property (strong, nonatomic) IBOutlet UISearchBar *search;

-(void)resetSearch;

//重置搜索,即恢复到没有输入关键字的状态

-(void)handleSearchForTerm:(NSString *)searchTerm;

//处理搜索,即把不包含searchTerm的值从可变数组中删除

@end

PDViewController.m:

[cpp] view
plaincopy

#import "PDViewController.h"

#import "NSDictionary+MutableDeepCopy.h"

@implementation PDViewController

@synthesize names=_names;

@synthesize mutableKeys=_mutableKeys;

@synthesize table = _table;

@synthesize search = _search;

@synthesize mutableNames=_mutableNames;

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.

}

#pragma mark - View lifecycle

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

NSString *path=[[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];

//取得sortednames.plist绝对路径

//sortednames.plist本身是一个NSDictionary,以键-值的形式存储字符串数组

NSDictionary *dict=[[NSDictionary alloc] initWithContentsOfFile:path];

//转换成NSDictionary对象

self.names=dict;

[self resetSearch];

//重置

[_table reloadData];

//重新载入数据

}

- (void)viewDidUnload

{

[self setTable:nil];

[self setSearch:nil];

[super viewDidUnload];

self.names=nil;

self.mutableKeys=nil;

self.mutableNames=nil;

// Release any retained subviews of the main view.

// e.g. self.myOutlet = nil;

}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

// Return YES for supported orientations

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

//返回分组数量,即Array的数量

return [_mutableKeys count];

//

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

if ([_mutableKeys count]==0) {

return 0;

}

NSString *key=[_mutableKeys objectAtIndex:section];

NSArray *nameSection=[_mutableNames objectForKey:key];

return [nameSection count];

//返回Array的大小

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

NSUInteger section=[indexPath section];

//分组号

NSUInteger rowNumber=[indexPath row];

//行号

//即返回第section组,rowNumber行的UITableViewCell

NSString *key=[_mutableKeys objectAtIndex:section];

//取得第section组array的key

NSArray *nameSection=[_mutableNames objectForKey:key];

//通过key,取得Array

static NSString * tableIdentifier=@"CellFromNib";

UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:tableIdentifier];

if(cell==nil)

{

cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];

}

cell.textLabel.text=[nameSection objectAtIndex:rowNumber];

//从数组中读取字符串,设置text

return cell;

}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

{

if ([_mutableKeys count]==0) {

return 0;

}

NSString *key=[_mutableKeys objectAtIndex:section];

return key;

}

-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

{

return _mutableKeys;

//通过key来索引

}

-(void)resetSearch

{//重置搜索

_mutableNames=[_names mutableDeepCopy];

//使用mutableDeepCopy方法深复制

NSMutableArray *keyarr=[NSMutableArray new];

[keyarr addObjectsFromArray:[[_names allKeys] sortedArrayUsingSelector:@selector(compare:)]];

//读取键,排序后存放可变数组

_mutableKeys=keyarr;

}

-(void)handleSearchForTerm:(NSString *)searchTerm

{//处理搜索

NSMutableArray *sectionToRemove=[NSMutableArray new];

//分组待删除列表

[self resetSearch];

//先重置

for(NSString *key in _mutableKeys)

{//循环读取所有的数组

NSMutableArray *array=[_mutableNames valueForKey:key];

NSMutableArray *toRemove=[NSMutableArray new];

//待删除列表

for(NSString *name in array)

{//数组内的元素循环对比

if([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location==NSNotFound)

{

//rangeOfString方法是返回NSRange对象(包含位置索引和长度信息)

//NSCaseInsensitiveSearch是忽略大小写

//这里的代码会在name中找不到searchTerm时执行

[toRemove addObject:name];

//找不到,把name添加到待删除列表

}

}

if ([array count]==[toRemove count]) {

[sectionToRemove addObject:key];

//如果待删除的总数和数组元素总数相同,把该分组的key加入待删除列表,即不显示该分组

}

[array removeObjectsInArray:toRemove];

//删除数组待删除元素

}

[_mutableKeys removeObjectsInArray:sectionToRemove];

//能过待删除的key数组删除数组

[_table reloadData];

//重载数据

}

-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

{//TableView的项被选择前触发

[_search resignFirstResponder];

//搜索条释放焦点,隐藏软键盘

return indexPath;

}

-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar

{//按软键盘右下角的搜索按钮时触发

NSString *searchTerm=[searchBar text];

//读取被输入的关键字

[self handleSearchForTerm:searchTerm];

//根据关键字,进行处理

[_search resignFirstResponder];

//隐藏软键盘

}

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

{//搜索条输入文字修改时触发

if([searchText length]==0)

{//如果无文字输入

[self resetSearch];

[_table reloadData];

return;

}

[self handleSearchForTerm:searchText];

//有文字输入就把关键字传给handleSearchForTerm处理

}

-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar

{//取消按钮被按下时触发

[self resetSearch];

//重置

searchBar.text=@"";

//输入框清空

[_table reloadData];

[_search resignFirstResponder];

//重新载入数据,隐藏软键盘

}

@end

mutableDeepCopy深复制的方法在NSDictionary+MutableDeepCopy定义,参考iOS/Objective-C开发
字典NSDictionary的深复制(使用category)

转自http://www.pocketdigi.com/20120323/726.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐