UISearchBar和 UISearchDisplayController的使用
来源:互联网 发布:html标签id使用js变量 编辑:程序博客网 时间:2024/05/17 08:56
UISearchBar和 UISearchDisplayController的使用
感觉好多文章不是很全面,所以本文收集整合了网上的几篇文章,感觉有互相补充的效果。
如果想下载源码来看:http://code4app.com/search/searchbar 。本源码与本文无关
1、searchBar
本例子实现布局:上面是一个navigationController,接下来一个searchBar,下面是tableView
searchBar这个控件就用来搜索tableView上的数据
[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
UISearchDisplayController这个控件很强大,它初始化是基于searchBar的,里面有些效果很不错,apple都封装好了,并且可以很好的支持实时搜索,即我们只需要将搜索出来的数据重新赋给array(这个array用来存储tableView数据),不需要reloadData,就会自动出来
其实reloadData也没用,为什么呢?因为搜索出来的结果显示在tableView上,该tableView并不是当前布局的那个tableView,而是另外一个,我猜测应该是UISearchDisplayController里面自带的,所以不要混淆了
特别是在tableView代理方法里,有时候需要判断代理方法传入的tableView是否为当前布局的tableView,因为也有可能是UISearchDisplayController里自带的,它们同样会触发代理方法
当点击searchBar时,它会自动上移并且遮住navigationController
经过测试,如果上面是navigationBar,则searchBar不会移动,但如果是UINavigationController自带过来的,则会上移覆盖
往往有的时候都是UINavigationController自带过来的,如果使用UISearchDisplayController,searchBar就会自动覆盖,这个情况我试了很多次,包括新创建了一个navigationBar盖在上面,但效果依然不好,对于这种情况,基于我目前的技术,只能舍弃UISearchDisplayController,单纯的用UISearchBar了,虽然效果差了一些,但需要实现的功能照样可以,比如实时搜索,除了重新赋值给array外,额外的操作就是需要reloadData了。
有时候点击searchBar时,右侧可能没有出现‘cancel/取消’按钮,这时需要调用下面的方法
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated
相信看方法名字就知道是做什么的了
来源:http://www.cnblogs.com/mobiledevelopment/archive/2011/08/04/2127633.html
2、iOS开发 给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:
123456789101112131415
#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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
#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)
3、Search Bar and Search DisplayController的实现
新建Navigation-based Project。打开.xib文件,拖一个Search Bar and Search DisplayController 对象到Table View对象上方,如下图所示,选中File’s Owner ,打开Connections面板:
现在我们来创建Search Bar和SearchDisplay Controller的出口。打开Assistant Editor,按住ctrl键,将SearchDisplay Controller拖到ViewController 的头文件中。创建一个名为searchDisplayController的出口,然后点Connect。
同样的方法为Search Bar创建连接。现在ViewController的头文件看起来像这样:
#import <UIKit/UIKit.h>
@interface RootViewController : UITableViewController {
UISearchDisplayController *searchDisplayController; UISearchDisplayController *searchBar;
NSArray *allItems;
NSArray *searchResults;
}
@property (nonatomic, retain) IBOutlet UISearchDisplayController *searchDisplayController;
@property (nonatomic, retain) IBOutlet UISearchDisplayController *searchBar;
@property (nonatomic, copy) NSArray *allItems;
@property (nonatomic, copy) NSArray *searchResults;
@end
你可能注意到,我初始化了两个NSArray。一个用于作为数据源,一个用于保存查找结果。在本文中,我使用字符串数组作为数据源。继续编辑.m文件前,别忘了synthesize相关属性:
@synthesize searchDisplayController;
@synthesize searchBar;
@synthesize allItems;
@synthesize searchResults;
在viewDidLoad 方法中,我们构造了我们的字符串数组:
- (void)viewDidLoad {
[super viewDidLoad];
// [self.tableView reloadData];
self.tableView.scrollEnabled = YES;
NSArray *items = [[NSArray alloc] initWithObjects: @"Code Geass", @"Asura Cryin'", @"Voltes V", @"Mazinger Z", @"Daimos", nil];
self.allItems = items;
[items release];
[self.tableView reloadData];
}
在Table View的返回TableView行数的方法中,我们先判断当前Table View是否是searchDisplayController的查找结果表格还是数据源本来的表格,然后返回对应的行数:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
rows = [self.searchResults count];
}else{
rows = [self.allItems count];
}
return rows;
}
在tableView:cellForRowAtIndexPath:方法里,我们需要做同样的事:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
/* Configure the cell. */
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}else{
cell.textLabel.text = [self.allItems objectAtIndex:indexPath.row];
}
return cell;
}
现在来实现当搜索文本改变时的回调函数。这个方法使用谓词进行比较,并讲匹配结果赋给searchResults数组:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", searchText];
self.searchResults = [self.allItems filteredArrayUsingPredicate:resultPredicate];
}
接下来是UISearchDisplayController的委托方法,负责响应搜索事件:
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;
}
运行工程,当你在搜索栏中点击及输入文本时,如下图所示:
4、UISearchBar的使用以及下拉列表框的实现
在IOS混饭吃的同志们都很清楚,搜索框在移动开发应用中的地位。今天我们就结合下拉列表框的实现来聊聊UISearchBar的使用。本人新入行的菜鸟一个,不足之处请多多指教。直接上代码。
UISearchBar控件的声明:(在控制器DownListViewController中)
- @property (nonatomic,retain) UISearchBar* searchBar;
控件的初始化:
- _searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
- _searchBar.placeholder = @"test"; //设置占位符
- _searchBar.delegate = self; //设置控件代理
当然,做完这些工作之后,我们还要在将控件添加到父视图之上,也可以把他设置成UITableView的tableHeaderView属性值,由于大家需求不一,这里就不再给出代码。
前面,我们设置了控件的代理,当然我们必须让控制器(DownListViewController)的 .h 文件实现 UISearchBarDelegate 协议,然后我们继续, 我们要在 .m 文件中实现协议方法:
- #pragma mark -
- #pragma mark UISearchBarDelegate
- //搜索框中的内容发生改变时 回调(即要搜索的内容改变)
- - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
- NSLog(@"changed");
- if (_searchBar.text.length == 0) {
- [self setSearchControllerHidden:YES]; //控制下拉列表的隐现
- }else{
- [self setSearchControllerHidden:NO];
- }
- }
- - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
- searchBar.showsCancelButton = YES;
- for(id cc in [searchBar subviews])
{
if([cc isKindOfClass:[UIButton class]])
{
UIButton *btn = (UIButton *)cc;
[btn setTitle:@"取消" forState:UIControlStateNormal];
}
} - NSLog(@"shuould begin");
- return YES;
- }
- - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
- searchBar.text = @"";
- NSLog(@"did begin");
- }
- - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
- NSLog(@"did end");
- searchBar.showsCancelButton = NO;
- }
- - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
- NSLog(@"search clicked");
- }
- //点击搜索框上的 取消按钮时 调用
- - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
- NSLog(@"cancle clicked");
- _searchBar.text = @"";
- [_searchBar resignFirstResponder];
- [self setSearchControllerHidden:YES];
- }
至此,搜索框的实现就搞定了,怎么样简单吧。下面我们来讲讲下拉列表框的实现,先说说他的实现原理或者是思路吧。下拉列表框我们用一个控制器来实现,我们新建一个控制器SearchViewController.
- @interface SearchViewController : UITableViewController
- @end
在 .m 文件中,我们实现该控制器
- - (id)initWithStyle:(UITableViewStyle)style
- {
- self = [super initWithStyle:style];
- if (self) {
- // Custom initialization
- }
- return self;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.tableView.layer.borderWidth = 1;
- self.tableView.layer.borderColor = [[UIColor blackColor] CGColor];
- }
然后实现控制器的数据源,
- #pragma mark -
- #pragma mark Table view data source
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- // 返回列表框的下拉列表的数量
- return 3;
- }
- // Customize the appearance of table view cells.
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *CellIdentifier = @"Cell";
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if (cell == nil) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
- }
- // Configure the cell...
- NSUInteger row = [indexPath row];
- cell.textLabel.text = @"down list";
- return cell;
- }
这样列表框的控制器就实现了。接下来我们就来看看怎么让出现、隐藏。这点我们利用UIView的动画效果来实现,我们在DownListViewController控制器中 增加一个方法:
- - (void) setSearchControllerHidden:(BOOL)hidden {
- NSInteger height = hidden ? 0: 180;
- [UIView beginAnimations:nil context:nil];
- [UIView setAnimationDuration:0.2];
- [_searchController.view setFrame:CGRectMake(30, 36, 200, height)];
- [UIView commitAnimations];
- }
我们只需调用该方法就可以了。现在我们看看DownListViewController的布局方法
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- _searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
- _searchBar.placeholder = @"test";
- _searchBar.delegate = self;
- _tableview = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
- _tableview.dataSource = self;
- _tableview.tableHeaderView = _searchBar;
- _searchController = [[SearchViewController alloc] initWithStyle:UITableViewStylePlain];
- [_searchController.view setFrame:CGRectMake(30, 40, 200, 0)];
- [self.view addSubview:_tableview];
- [self.view addSubview:_searchController.view];
- }
这样一切都搞定了。
好了,总结一下:
我们用了两个控制器:DownListViewController(搜索框的实现 和 控制下拉列表框的出现与隐藏)和SearchViewController(下拉列表框的实现)。在DownListViewController中我们声明并初始化 UISearchBar和SearchViewController(高度开始设置为零),用动画来实现下拉列表框的出现与隐藏。
本文出自 “开发问道” 博客,请务必保留此出处http://izhuaodev.blog.51cto.com/6266344/1102408
- UISearchBar和 UISearchDisplayController的使用
- UISearchBar和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- UISearchBar 和 UISearchDisplayController的使用
- iOS UISearchBar 和 UISearchDisplayController的使用
- 关于UISearchDisplayController和 uisearchBar使用时遇到的问题
- IOS UISearchBar + UISearchDisplayController使用
- UISearchBar和UISearchDisplayController
- UISearchBar和UISearchDisplayController
- android studio 导入自定义编码格式
- VC Preprocessor definitions
- Myeclipse或Eclipse 老是出现JPA project Change Event Handler
- Java中List的排序 Comparable和 Compartor
- 非oracle用户无法登陆数据库 ora 12547
- UISearchBar和 UISearchDisplayController的使用
- SharePoint 2013的社交功能之(三)规划Mysite
- Linux 平时用到的基本命令
- Freescale WINCE 6.0休眠唤醒后声音消失,原因居然是驱动线程优先级不够
- 111
- Mac上使用protobuf
- sping 多数据源配置
- linux下查看和修改文件时间
- 页面之间传值之delegate委托传值