问题
So I have a textField, which when the user presses, it shows a UIPickerView, which is populated from an array.
Is it possible for there to be search bar at the top of the pickerView, so the user can search for something in the pickerView?
I've not seen this done before so have no idea if it's possible?
Thanks in advance.
回答1:
UIPickerView
is really meant for a few options - if you need to present something that has a lot more options, I would suggest a table view with a search bar. Search Bar Tutorial is a good start.
回答2:
Here is an easy solution which I have used on my recent project. First of all you need to concentrate on the following points.
- Try to use UITextfield for better customization
- Use table view to populate data easily inside your main viewController class.
- Avoid using segue thing which is little bit annoying and old fashioned.
- Try to make your code more realistic and hassle-free.
First things first :- I am using Xcode 7.2.2 with Swift 2.1
Using native filter method to filter form the array and reuse that.
Using Array of Array type Dictionary(Swift)
Concentrating on the above points.. :)
Here is my class file. Go through the code and you will understand...
import UIKit
class ComposeMessageClass: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
var filtered = [[String : String]]()
let customerNameForSearch: [[String : String]] = [["name": "Tuhin"], ["name": "Superman"], ["name" : "Rahul"], ["name": "Batman"], ["name": "Spiderman"]]
let customerNameToSearchTemp = ["Tuhin", "Superman", "Rahul", "Batman", "Spiderman"]
var searchActive: Bool = false
@IBOutlet weak var autofillTable: UITableView!
@IBOutlet weak var autofillTableView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.autofillTableView.hidden = true
self.autofillTable.delegate = self
self.autofillTable.dataSource = self
self.autofillTable.backgroundColor = tableViewBackGroundColor
self.autofillTable.separatorColor = tableViewSeperatorColor
self.autofillTable.layer.borderColor = tableViewBorderColor
}
}
override func viewWillAppear(animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
}
func textFieldDidBeginEditing(textField: UITextField) {
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var updatedTextString : NSString = textField.text! as NSString
updatedTextString = updatedTextString.stringByReplacingCharactersInRange(range, withString: string)
self.filtered.removeAll()
self.customerNameToSearchTemp.filter({ (text) -> Bool in
let tmp: NSString = text
let range = tmp.rangeOfString(updatedTextString as String, options: NSStringCompareOptions.CaseInsensitiveSearch)
if range.location != NSNotFound{
let dataArr = ["name": tmp as String]
filtered.append(dataArr)
}
return false
}
})
if(filtered.count == 0){
filtered = [["name" : "No results found"]]
searchActive = true
} else {
searchActive = true;
}
self.autofillTable.reloadData()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(searchActive) {
return self.filtered.count
}
return self.customerNameForSearch.count
}
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.autofillTable.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.backgroundColor = UIColor.clearColor()
cell.textLabel!.textColor = tableViewCellTextColorGreen
cell.textLabel!.textAlignment = .Center
cell.selectionStyle = .None
cell.textLabel!.font = UIFont(name: "System", size:17)
if(searchActive){
if filtered[indexPath.row]["name"]! == "No results found"{
cell.textLabel!.text = self.filtered[indexPath.row]["name"]!
cell.userInteractionEnabled = false
}else{
cell.userInteractionEnabled = true
cell.textLabel?.text = self.filtered[indexPath.row]["name"]!
}
} else {
cell.userInteractionEnabled = true
cell.textLabel?.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
}
return cell
}
internal func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if(self.autofillTable.respondsToSelector(Selector("setSeparatorInset:"))){
self.autofillTable.separatorInset = UIEdgeInsetsZero
}
if(self.autofillTable.respondsToSelector(Selector("setLayoutMargins:"))){
self.autofillTable.layoutMargins = UIEdgeInsetsZero
}
if(cell.respondsToSelector(Selector("setLayoutMargins:"))){
cell.layoutMargins = UIEdgeInsetsZero
}
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.backgroundColor = UIColor.clearColor()
cell?.textLabel?.textColor = tableViewCellTextColorGreen
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.backgroundColor = UIColor.blackColor()
cell?.textLabel?.textColor = tableViewCellTextColorWhite
self.selectedCustomerId.removeAll()
if(searchActive){
self.contactNameTxtFld.text = self.filtered[indexPath.row]["name]!
}else{
self.contactNameTxtFld.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
self.view.endEditing(true)
}
}
Example to set over the storyboard.
Thanks.
Hope this helped.
Any Modification or suggestion our questions would be appreciated.
回答3:
- I added a custom header view for the table with a textField insted of searcontroller(searchbar) and cancel button programmatically with little custmization to the tableView.
- I added the following code to filter and get the updated search results
class ViewController: UIViewController,UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource{
let speciality=["Andhra","Bhihar","uttharPradesh","kerala","karnataka","kashmir","thamilnadu","assam","jarkhand","dolapure","manjil","udaypoor","sholapoor","Atthapure","Barampure","Khasi"]
var filteredArray = [String]()
var shouldShowSearchResults = false
var tableView:UITableView!
var yaxis:CGFloat=10
var txtdateOfOperation:UITextField!
var searchTextField:UITextField!
var cancelButton:UIButton!
override func viewDidLoad() {
let dateOfOperationLabel=UILabel(frame:CGRectMake(8,100,200,16))
dateOfOperationLabel.text="State"
dateOfOperationLabel.textColor=UIColor.blackColor()
dateOfOperationLabel.textAlignment=NSTextAlignment.Left
dateOfOperationLabel.font = UIFont.systemFontOfSize(13.0)
dateOfOperationLabel.numberOfLines = 0;
self.view.addSubview(dateOfOperationLabel)
txtdateOfOperation=UITextField(frame: CGRectMake(8,130,300,28))
txtdateOfOperation.borderStyle=UITextBorderStyle.RoundedRect
txtdateOfOperation.returnKeyType=UIReturnKeyType.Done
txtdateOfOperation.userInteractionEnabled=true
txtdateOfOperation.keyboardType=UIKeyboardType.NumberPad
self.view.addSubview(txtdateOfOperation)
tableView=UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate=self
tableView.dataSource=self
tableView.reloadData()
let view=UIView(frame:CGRectMake(0,0,UIScreen.mainScreen().bounds.width,35))
view.backgroundColor=UIColor.lightGrayColor()
searchTextField=UITextField(frame:CGRectMake(8,3,view.bounds.width-70,28))
searchTextField.borderStyle=UITextBorderStyle.RoundedRect
searchTextField.returnKeyType=UIReturnKeyType.Done
searchTextField.userInteractionEnabled=true
searchTextField.delegate=self
searchTextField.placeholder="Search Here..."
searchTextField.clearButtonMode = .WhileEditing
searchTextField.leftViewMode = UITextFieldViewMode.Always
searchTextField.leftView = UIImageView(image: UIImage(named: "search-icon"))
searchTextField.addTarget(self, action: #selector(searchTextFieldDidBeginEdit), forControlEvents: UIControlEvents.EditingChanged)
view.addSubview(searchTextField)
cancelButton=UIButton(frame:CGRectMake(view.bounds.width-65,3,70,28))
cancelButton.setTitle("Cancel", forState: UIControlState.Normal)
cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
cancelButton.addTarget(self, action: #selector(searchBarCancelButton_Click), forControlEvents: UIControlEvents.TouchUpInside)
cancelButton.userInteractionEnabled=false
view.addSubview(cancelButton)
tableView.tableHeaderView = view
txtdateOfOperation.inputView=tableView
searchTextField.inputView=tableView
self.tableView.reloadData()
}
func textFieldDidBeginEditing(textField: UITextField) {
shouldShowSearchResults = true
cancelButton.userInteractionEnabled=true
cancelButton.setTitleColor(UIColor(red: 51/255, green: 153/255, blue: 255/255, alpha: 1.0), forState: UIControlState.Normal)
tableView.reloadData()
}
func textFieldDidEndEditing(textField: UITextField) {
cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
}
func searchTextFieldDidBeginEdit(textField:UITextField) {
if let searchText=textField.text{
filteredArray = speciality.filter({ (country) -> Bool in
let countryText: NSString = country
return (countryText.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch).location) != NSNotFound
})
tableView.reloadData()
}
}
func searchBarCancelButton_Click(){
searchTextField.text=nil
searchTextField.resignFirstResponder()
shouldShowSearchResults = false
tableView.reloadData()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowSearchResults {
return filteredArray.count
}
else {
return speciality.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if shouldShowSearchResults {
cell.textLabel?.text = filteredArray[indexPath.row]
}
else {
cell.textLabel?.text = speciality[indexPath.row]
}
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if shouldShowSearchResults{
txtdateOfOperation.text=filteredArray[indexPath.row]
searchTextField.text=nil
searchTextField.resignFirstResponder()
txtdateOfOperation.resignFirstResponder()
shouldShowSearchResults=false
filteredArray=[String]()
tableView.reloadData()
}
else{
txtdateOfOperation.text=speciality[indexPath.row]
searchTextField.resignFirstResponder()
tableView.resignFirstResponder()
txtdateOfOperation.resignFirstResponder()
}
}
}
i tested it and its working perfectly
来源:https://stackoverflow.com/questions/30297135/search-bar-at-the-top-of-a-uipickerview-in-swift