系统自带的搜索栏是继承于UIView的,封装TextField等UIView,但是这些控件并不能对外可见。
public init(frame: CGRect)
public init?(coder aDecoder: NSCoder)
基本属性
open var barStyle: UIBarStyle // default is UIBarStyleDefault (blue),其他值白色,黑色,黑色半透明
weak open var delegate: UISearchBarDelegate? // weak reference. default is nil
open var text: String? // current/starting search text
open var prompt: String? // 附加字符串default is nil
open var placeholder: String? //占位字符(灰色) default is nil
open var showsBookmarkButton: Bool // default is NO
open var showsCancelButton: Bool // 是否添加取消按钮default is NO
@available(iOS 3.2, *)
open var showsSearchResultsButton: Bool // default is NO
@available(iOS 3.2, *)
open var isSearchResultsButtonSelected: Bool // 是否显示选中按钮default is NO
open var inputAssistantItem: UITextInputAssistantItem { get }
open var tintColor: UIColor! //设置tint颜色
open var barTintColor: UIColor? // default is nil
open var searchBarStyle: UISearchBarStyle //搜索栏样式,有三个值,默认(输入框外侧灰暗)、输入框内侧灰暗
open var isTranslucent: Bool // 默认值为false 设置半透明,如果barstyle设置为半透明,则为半透明
open var scopeButtonTitles: [String]? // 分割栏标题数组,如果设置就会有一个分割栏在搜索栏下面
open var selectedScopeButtonIndex: Int // 显示选中分割栏的下标,不设置默认为0
open var showsScopeBar: Bool // default is NO. if YES, shows the scope bar. call sizeToFit: 该方法可以更新设置frame
open var inputAccessoryView: UIView? //输入框的遮掩视图【即在选中输入框时,除了输入框之外的空间,为它设置视图,如电话本的选中搜索栏后,其他区域的半透明黑色视图】
open var backgroundImage: UIImage? //背景图
open var scopeBarBackgroundImage: UIImage? //分隔栏的背景图
下面就是一些方法
//设置和获取背景图(一般为搜索框外部的)
open func setBackgroundImage(_ backgroundImage: UIImage?, for barPosition: UIBarPosition, barMetrics: UIBarMetrics) // Use UIBarMetricsDefaultPrompt to set a separate backgroundImage for a search bar with a prompt
open func backgroundImage(for barPosition: UIBarPosition, barMetrics: UIBarMetrics) -> UIImage?
//设置和获取搜索框内部的背景图(含控制状态)
open func setSearchFieldBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState)
open func searchFieldBackgroundImage(for state: UIControlState) -> UIImage?
//设置某个icon,某种控制状态的图片
open func setImage(_ iconImage: UIImage?, for icon: UISearchBarIcon, state: UIControlState)
open func image(for icon: UISearchBarIcon, state: UIControlState) -> UIImage?
open func setScopeBarButtonBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState)
open func scopeBarButtonBackgroundImage(for state: UIControlState) -> UIImage?
//设置和获取分割栏按钮的某种状态的背景图
open func setScopeBarButtonDividerImage(_ dividerImage: UIImage?, forLeftSegmentState leftState: UIControlState, rightSegmentState rightState: UIControlState)
open func scopeBarButtonDividerImage(forLeftSegmentState leftState: UIControlState, rightSegmentState rightState: UIControlState) -> UIImage?
//设置和获取分割栏字体状态属性
open func setScopeBarButtonTitleTextAttributes(_ attributes: [String : Any]?, for state: UIControlState)
open func scopeBarButtonTitleTextAttributes(for state: UIControlState) -> [String : Any]?
//设置文本框背景的偏移量
open var searchFieldBackgroundPositionAdjustment: UIOffset
// 设置文本框中文本的便宜量
open var searchTextPositionAdjustment: UIOffset
//设置和获取icon图标的偏移量
open func setPositionAdjustment(_ adjustment: UIOffset, for icon: UISearchBarIcon)
open func positionAdjustment(for icon: UISearchBarIcon) -> UIOffset
通过搜索栏并没有TextField的属性开发,可以通过kvc 获取到TextField,示例代码
if let textField = self.value(forKey: "searchField") as? UITextField {
// 设置textField 的各项属性,比如背景色。圆角等
}
由于搜索栏遵循了UITextInputTraits(文本输入类都遵循了)
还可以设置协议属性控制,以下属性都是可选实现的。
//
autocapitalizationType: UITextAutocapitalizationType { get set } // default is UITextAutocapitalizationTypeSentences
//自动检查类型 (值有:不检查,检查所有字符、检查单词、检查句子)
(值有:不检查,检查所有字符、检查单词、检查句子)
autocorrectionType: UITextAutocorrectionType { get set } // default is UITextAutocorrectionTypeDefault
//拼写检查
spellCheckingType: UITextSpellCheckingType { get set } // default is UITextSpellCheckingTypeDefault;
//键盘类型
keyboardType: UIKeyboardType { get set } // default is UIKeyboardTypeDefault
//
keyboardAppearance: UIKeyboardAppearance { get set } // default is UIKeyboardAppearanceDefault
//返回键类型(字面值不一样)
returnKeyType: UIReturnKeyType { get set } // default is UIReturnKeyDefault (See note under UIReturnKeyType enum)
//自动返回值
enablesReturnKeyAutomatically: Bool { get set } // default is NO (when YES, will automatically disable return key when text widget has zero-length contents, and will automatically enable when text widget has non-zero-length contents)
//安全输入(将输入变为*)如输入密码时
isSecureTextEntry: Bool { get set } // default is NO
//文本内容类型
// The textContentType property is to provide the keyboard with extra information about the semantic intent of the text document.
textContentType: UITextContentType! { get set } // default is nil
该代理主要处理搜索栏的第一响应器、文本改变处理、文本编辑处理;几个按钮事件回掉和scoped时间回掉。
常用方法如下
optional public func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool // 如果像让搜索栏不成为第一响应器,可以返回NO值
//文本编辑时调用
optional public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) // called when text starts editing
//返回NO注销搜索栏的第一响应
optional public func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool // return NO to not resign first responder
//结束编辑时调用
optional public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) // called when text ends editing
//文本改变时调用
optional public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) // called when text changes (including clear)
//文本改变之前调用
optional public func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool // called before text changes
//点击键盘搜索时调用,处理搜索过滤。
optional public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) // called when keyboard search button pressed
//书签点击回掉
optional public func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) // called when bookmark button pressed
//取消按钮点击调用
optional public func searchBarCancelButtonClicked(_ searchBar: UISearchBar) // called when cancel button pressed
//结果列表按钮点击回掉
optional public func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) // called when search results button pressed
//当分割栏点击改变时调用。
optional public func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)
这个控件的功能不是那么复杂,总体实现比较简单,大部分属性都可以使用IB的可视化设置。
目前只通过代码方式(为导航栏的视图添加子视图方案)实现,无法直接实现通过拖控件的方法实现(即时实现也有视图被剪切,不知道是不是某些设置问题)。
代码如下:
var searchBar = UISearchBar(frame: CGRect(x:0 , y: 20, width: UIScreen.main.bounds.width, height: (self.navigationController?.navigationBar.bounds.height)!)) //y值设置20,否则导航栏将有可能在状体栏底层。
searchBar.delegate = self //注意实现代理,也可以进行其他配置
self.navigationController?.view.addSubview(searchBar)//是在它的view下添加子view
运行结果图:
在设置之前,你需要明白,我们看到的导航栏其实是导航栏(UINavigationBar)的背景图片,而不是背景色,所以设置背景色是无法实现透明的。
可以设置全透明的图片作为背景图和shadowImage(下面的那根线).
一个更简单的方法,直接创建两掌无内容的图片实例放在那里。
代码如下:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage() //这个也要设置,否则有一条白线。
首先得知道UiSearchController不是一个容器控制类,而是相当于搜索栏工具类。
UISearchController是UISearchBar+DisplayViewController的替代品,是iOS8之后的接口类
这里需要学习一下面向协议编程,当有多个代理协议时
官方文档
代码如下:
import UIKit
class TextViewController: UIViewController {
var searchController:UISearchController!
var tableView:UITableView!
//偷的航哥的数据
var rawDatasour = ["清华大学","北京大学","中国人民大学","北京交通大学","北京工业大学",
"北京航空航天大学","北京理工大学","北京科技大学","中国政法大学",
"中央财经大学","华北电力大学","北京体育大学","上海外国语大学","复旦大学",
"华东师范大学","上海大学","河北工业大学"]
//过滤数组
var filterArray = [String](){
didSet{
tableView.reloadData() //很巧妙
}
}
var cell:UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
initTableView()
initSearchController()
self.view.addSubview(tableView)
//【特别重要】搜索栏放tableView的HeaderView上
tableView.tableHeaderView = searchController.searchBar
//self.view.addSubview(searchController.searchBar)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK:自定义方法
//配置tableView
func initTableView() -> Void {
var tableViewFrame = CGRect(x: 0, y: 20, width: self.view.bounds.width, height: self.view.bounds.height-20)
tableView = UITableView(frame:tableViewFrame , style: .plain)
tableView.delegate = self
tableView.dataSource = self
}
//提示一下:SearchController,内部默认实现的将导航栏影藏,放搜索栏,可以设置
func initSearchController() -> Void {
searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self
searchController.searchResultsUpdater = self
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.showsCancelButton = false
searchController.searchBar.delegate = self
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
//通过表格实现数据的显示。
//MARK:--UITableViewDelegate,UITableViewDataSource
extension TextViewController:UITableViewDelegate,UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive {//记得需要同步更改行数,然会数据展示出错
return filterArray.count
}else{
return rawDatasour.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = UITableViewCell(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.tableView.rowHeight))
//注意这里的数据源根据searchController的active(选中、编辑、点击搜索,直到取消)切换
if searchController.isActive { //搜索状态
cell.textLabel?.text = filterArray[indexPath.row]
}else{
cell.textLabel?.text = rawDatasour[indexPath.row]
}
return cell
}
}
//代理的实现
//MARK:UISearchBarDelegate
extension TextViewController:UISearchResultsUpdating,UISearchBarDelegate,UISearchControllerDelegate{
//实时响应,当成为第一响应的时候,或者文本改变的时候调用。
//当样本数据量很大的时候不建议使用
func updateSearchResults(for searchController: UISearchController) {
filterArray = rawDatasour.filter({ (str) -> Bool in
return str.contains((searchController.searchBar.text!))
})
}
//点击按钮之后再调用,适合大量数据显示的时候
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
filterArray = rawDatasour.filter({ (str) -> Bool in
return str.contains((searchController.searchBar.text!))
})
}
//TODO:怎么将按钮设置为中文,或者自定义样式(难道要使用runtime?)
func willPresentSearchController(_ searchController: UISearchController) {
}
}
运行结果图:
搜索结果: