Swift 中 UIPickerView 顶部的搜索栏
Search bar at the top of a UIPickerView in Swift
所以我有一个 textField,当用户按下它时,它会显示一个 UIPickerView,它是从一个数组中填充的。
是否可以在 pickerView 的顶部有搜索栏,以便用户可以在 pickerView 中搜索内容?
我以前从未见过这样做,所以不知道是否可行?
提前致谢。
UIPickerView
实际上意味着一些选项 - 如果您需要展示具有更多选项的内容,我建议使用带有搜索栏的 table 视图。 Search Bar Tutorial 是一个好的开始。
这是我在最近的项目中使用的一个简单的解决方案。首先你需要关注以下几点。
- 尝试使用 UITextfield 进行更好的自定义
- 使用 table 视图在您的主视图中轻松填充数据 viewController class.
- 避免使用有点烦人且过时的 segue 东西。
- 尽量让你的代码更真实,hassle-free。
要事第一 :-
我正在使用 Xcode 7.2.2 和 Swift 2.1
使用本机过滤方法从数组中过滤并重复使用。
使用数组类型字典的数组(Swift)
集中在以上几点.. :)
这是我的 class 文件。看完代码你就明白了...
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)
}
}
在情节提要上设置的示例。
谢谢。
希望对您有所帮助。
任何修改或建议我们的问题将不胜感激。
- 我为 table 添加了自定义 header 视图,其中包含 searcontroller(searchbar) 的文本字段,并以编程方式取消按钮,对 table 视图进行了很少的自定义。
- 我添加了以下代码来过滤并获取更新的搜索结果
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()
}
}
}
我测试了它,它运行良好
所以我有一个 textField,当用户按下它时,它会显示一个 UIPickerView,它是从一个数组中填充的。
是否可以在 pickerView 的顶部有搜索栏,以便用户可以在 pickerView 中搜索内容?
我以前从未见过这样做,所以不知道是否可行?
提前致谢。
UIPickerView
实际上意味着一些选项 - 如果您需要展示具有更多选项的内容,我建议使用带有搜索栏的 table 视图。 Search Bar Tutorial 是一个好的开始。
这是我在最近的项目中使用的一个简单的解决方案。首先你需要关注以下几点。
- 尝试使用 UITextfield 进行更好的自定义
- 使用 table 视图在您的主视图中轻松填充数据 viewController class.
- 避免使用有点烦人且过时的 segue 东西。
- 尽量让你的代码更真实,hassle-free。
要事第一 :- 我正在使用 Xcode 7.2.2 和 Swift 2.1
使用本机过滤方法从数组中过滤并重复使用。
使用数组类型字典的数组(Swift)
集中在以上几点.. :)
这是我的 class 文件。看完代码你就明白了...
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)
}
}
在情节提要上设置的示例。
谢谢。
希望对您有所帮助。
任何修改或建议我们的问题将不胜感激。
- 我为 table 添加了自定义 header 视图,其中包含 searcontroller(searchbar) 的文本字段,并以编程方式取消按钮,对 table 视图进行了很少的自定义。
- 我添加了以下代码来过滤并获取更新的搜索结果
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()
}
}
}
我测试了它,它运行良好