Alternative Autocomplete UITextField

本文介绍了一种自定义实现的搜索栏,该搜索栏具备自动完成功能,能够根据用户输入显示相关建议,并且外观上更接近Google搜索框的风格。

Alternative Autocomplete UITextField

6:30 pm in ConclavePresentation by Andrew Wimpy

For a project I am working on, I needed to implement a search bar that would automatically complete the word the user is typing into the search bar and display relevant results. However, I didn’t want this to work like the default search bar functionality in objective c where the search bar is tied to a table view that takes up most of the on screen real estate. Instead I needed this auto complete search bar to visually be more like the search bar on Google. I have attached an example Xcode Project that demonstrates this functionality on an iPhone.

As can be seen in the image above the only two objects needed to make this work are a UITextField and a UITableView. The UITextField will act as our search bar, and the UITableView will be populated with our auto complete elements. Other than that you just need to have the correct logic.

Step 1: Create Objects

First, we will be creating the UITextField and the UITableView. The table and text fields can be configured according to what is needed in your app, but I would always create the UITable with a width of about 2 to 4 pixels less than the text field. This will allow the auto complete functionality to be visually more like the Google search bar. The one thing to note is that the table is initially hidden. This is done because we only want the table to display when the user is typing into the text field.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Search Bar
txtField = [[UITextField alloc] initWithFrame:CGRectMake(5, 20, 261, 41)];
txtField.borderStyle = 3; // rounded, recessed rectangle
txtField.autocorrectionType = UITextAutocorrectionTypeNo;
txtField.textAlignment = UITextAlignmentLeft;
txtField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txtField.returnKeyType = UIReturnKeyDone;
txtField.font = [UIFont fontWithName:@ "Trebuchet MS" size:22];
txtField.textColor = [UIColor blackColor];
[txtField setDelegate:self];
[self.view addSubview:txtField];
[txtField release];
 
//Autocomplete Table
autoCompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(6, 56, 259, tableHeight) style:UITableViewStylePlain];
autoCompleteTableView.delegate = self;
autoCompleteTableView.dataSource = self;
autoCompleteTableView.scrollEnabled = YES;
autoCompleteTableView.hidden = YES;
autoCompleteTableView.rowHeight = tableHeight;
[self.view addSubview:autoCompleteTableView];
[autoCompleteTableView release];

We now need to create an array that will be what we are searching through to populate the autoCompleteTableView. I have included a text file with sample elements to populate this array. We first need to pull the contents of the file into memory and then convert the bytes from the file into a string. This string will then be split around newline characters to create our array. Finally, we will be creating our auto complete array that will hold the elements that correspond with what is being typed in the search bar.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Pull the content from the file into memory
NSString *filePath = [NSString stringWithFormat:@ "/Users/drewnextpression/AutoCompleteTextField/elements.txt" ];
NSData* data = [NSData dataWithContentsOfFile:filePath];
 
//Convert the bytes from the file into a string
NSString* string = [[[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSUTF8StringEncoding] autorelease];
 
//Split the string around newline characters to create an array
NSString* delimiter = @ "\n" ;
NSArray *item = [string componentsSeparatedByString:delimiter];
elementArray = [[NSMutableArray alloc] initWithArray:item];
autoCompleteArray = [[NSMutableArray alloc] init];

Step 2: Text Field Logic

As the user types into the text field, the text will be converted into a substring by using UITextfield’s delegate method shouldChangeCharactersInRange. Once this substring has been created, it will be passed to the method searchAutocompleteEntriesWithSubstring.

The method searchAutocompleteEntriesWithSubstring will compare the substring of the text field against the elements in the element array to see if any of the element’s beginning characters are the same as the substring. This is done by grabbing each element one at a time from the array of elements. An NSRange value is then created that will have the range and location of the substring in the element. Since I wanted the search to be case insensitive I have two different ranges. One NSRange will check for lowercase and another will check for uppercase.

Once these ranges are found, their length can be used to determine if the substring occurred at the beginning of the element. Since NSRange will return a length of 0 if the substring isn’t in the beginning of the current element, we can use this logic to only add elements to the autoCompleteArray that have an NSRange of length != 0.

Finally, the table needs to be unhidden since the user is typing into the text field, and it needs to be reloaded since it is being drawn based on the elements in the autoCompleteArray.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// String in Search textfield
- ( BOOL )textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
 
// Take string from Search Textfield and compare it with autocomplete array
- ( void )searchAutocompleteEntriesWithSubstring:(NSString *)substring {
 
// Put anything that starts with this substring into the autoCompleteArray
// The items in this array is what will show up in the table view
 
[autoCompleteArray removeAllObjects];
 
for (NSString *curString in elementArray) {
NSRange substringRangeLowerCase = [curString rangeOfString:[substring lowercaseString]];
NSRange substringRangeUpperCase = [curString rangeOfString:[substring uppercaseString]];
 
if (substringRangeLowerCase.length != 0 || substringRangeUpperCase.length != 0) {
[autoCompleteArray addObject:curString];
}
}
 
autoCompleteTableView.hidden = NO;
[autoCompleteTableView reloadData];
}

Step 3: TableView Logic

As noted in step 2, the table is being drawn based on the elements in the autoCompleteArray. If the array is empty, the table will be drawn with one empty cell. If the array has one element, the table will be drawn with one cell displaying this element. If the array has two elements, the table will be drawn with two cells displaying the elements. If the array has three elements or more, the table will be drawn with three cells and will be scrollable if there are more than three objects. The code for populating the table is found in the table delegate method cellForRowAtIndexPath, and the table drawing functionality is found in the tableview delegate method numberOfRowsInSection.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
 
//Resize auto complete table based on how many elements will be displayed in the table
if (autoCompleteArray.count >=3) {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight*3);
return autoCompleteArray.count;
}
 
else if (autoCompleteArray.count == 2) {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight*2);
return autoCompleteArray.count;
}
 
else {
autoCompleteTableView.frame = CGRectMake(6, 56, 259, tableHeight);
return autoCompleteArray.count;
}
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = @ "AutoCompleteRowIdentifier" ;
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];
}
 
cell.textLabel.text = [autoCompleteArray objectAtIndex:indexPath.row];
return cell;
}

When the user clicks on an element in the table, the textfield will be populated with that element and the method finishedSearching will be called. This method will close the keyboard and hide the table.

?
1
2
3
4
5
6
7
8
9
10
- ( void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
txtField.text = selectedCell.textLabel.text;
[self finishedSearching];
}
 
- ( void ) finishedSearching {
[txtField resignFirstResponder];
autoCompleteTableView.hidden = YES;
}

Step 4: Closing the Keyboard

I wanted the user to be able to close the keyboard by either pressing the Done button on the keyboard or tapping anywhere on the background. I used the text field’s delegate method textFieldShouldReturn to close the keyboard on a Done button press. Finally, I used the method touchesBegan: withEvent: to close the keyboard when the user touches the background.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Close keyboard when Enter or Done is pressed
- ( BOOL )textFieldShouldReturn:(UITextField *)textField {
BOOL isDone = YES;
 
if (isDone) {
[self finishedSearching];
return YES;
} else {
return NO;
}
}
 
// Close keyboard if the Background is touched
- ( void )touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
[self finishedSearching];
}

Step 5: Clean up and Release

At this point we need to release the autoCompleteArray and elementArray. The table and text field don’t need to be released since we already released them after we initialized them.

?
1
2
3
4
5
- ( void )dealloc {
[autoCompleteArray dealloc];
[elementArray dealloc];
[super dealloc];
}

That’s it! Download the AutoCompleteTextField project and give it a go. If you find any bugs or have any suggestions let me know.

Source Code: AutoCompleteTextField.zip

本课题设计了一种利用Matlab平台开发的植物叶片健康状态识别方案,重点融合了色彩与纹理双重特征以实现对叶片病害的自动化判别。该系统构建了直观的图形操作界面,便于用户提交叶片影像并快速获得分析结论。Matlab作为具备高效数值计算与数据处理能力的工具,在图像分析与模式分类领域应用广泛,本项目正是借助其功能解决农业病害监测的实际问题。 在色彩特征分析方面,叶片影像的颜色分布常与其生理状态密切相关。通常,健康的叶片呈现绿色,而出现黄化、褐变等异常色彩往往指示病害或虫害的发生。Matlab提供了一系列图像处理函数,例如可通过色彩空间转换与直方图统计来量化颜色属性。通过计算各颜色通道的统计参数(如均值、标准差及主成分等),能够提取具有判别力的色彩特征,从而为不同病害类别的区分提供依据。 纹理特征则用于描述叶片表面的微观结构与形态变化,如病斑、皱缩或裂纹等。Matlab中的灰度共生矩阵计算函数可用于提取对比度、均匀性、相关性等纹理指标。此外,局部二值模式与Gabor滤波等方法也能从多尺度刻画纹理细节,进一步增强病害识别的鲁棒性。 系统的人机交互界面基于Matlab的图形用户界面开发环境实现。用户可通过该界面上传待检图像,系统将自动执行图像预处理、特征抽取与分类判断。采用的分类模型包括支持向量机、决策树等机器学习方法,通过对已标注样本的训练,模型能够依据新图像的特征向量预测其所属的病害类别。 此类课题设计有助于深化对Matlab编程、图像处理技术与模式识别原理的理解。通过完整实现从特征提取到分类决策的流程,学生能够将理论知识与实际应用相结合,提升解决复杂工程问题的能力。总体而言,该叶片病害检测系统涵盖了图像分析、特征融合、分类算法及界面开发等多个技术环节,为学习与掌握基于Matlab的智能检测技术提供了综合性实践案例。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值