Q: 如果想要做到上圖所示的搜尋框需要怎麼設定?
搜尋框的樣式設定都是基於UISearchController
的searchBar
也就是UISearchBar
設定的。
但是UISearchBar
並沒有提供多少自定義設定。 圖示相關的設定也主要是系統提供的幾種簡單樣式。
而iOS11和iOS11以下的搜尋框由於樣式不一樣,很多屬性的設定不盡相同。
所以這篇文章就是對怎麼修改UISearchController
樣式的梳理
首先UISearchController
主要是對UISearchBar
的封裝,而UISearchBar
又包含了UITextField
和UINavigationButton
(取消按鈕)
一 UITextField設定
獲取TextField
有兩種方法可以獲取,KVC或者遍歷子檢視。
我們這裡採用KVC,效率比較高。
let searchField = searchBar.value(forKey: "searchField")
func findTextView(in view: UIView)->UITextField {
for view in searchBar.subviews[0].subviews {
if view is UITextField {
return view as! UITextField
}
}
return nil
}
複製程式碼
這裡的遍歷都是對
seachBar.subviews[0]
行遍歷,如果以後在某個版本比如iOS12中如果UISearchBar
的結構又發生了改變,那可能就找不到了。 所以如果要使用遍歷的話,還是遞迴seachBar
的所有子檢視去找比較保險。 改變屬性名稱的概率比較小,所以用KVO
相對安全一點。
1. 圖示
這裡我們討論三種圖示的設定
UISearchBarIcon.search
:這個是搜尋框左側的那個放大鏡圖示UISearchBarIcon.bookmark
:這個是搜尋框右側顯示的圖示,預設是不現實的。效果就是微信語音輸入的那個話筒一樣。UISearchBarIcon.clear
: 這個是在輸入過程中顯示的清除按鈕。
如果設定了bookmark,在沒有輸入的時候顯示bookmark,輸入的時候顯示清除按鈕
程式碼
這三種圖示都可以通過以下方法來設定。
searchBar.setImage(icon, for: .searchBar, state: .normal)
複製程式碼
除此之外也可以獲取具體的UI元件來設定 如果是想用預設的圖片但只是想改變其顏色的話,
1)可以通過下面這個方法來重繪顏色。把返回的圖片再通過setImage
來設定即可。
extension UIImage {
func reRender(with color: UIColor) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
if let context = UIGraphicsGetCurrentContext(), let cg = cgImage {
context.translateBy(x: 0, y: size.height)
context.scaleBy(x: 1.0, y: -1.0)
context.setBlendMode(.normal)
color.setFill()
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
context.clip(to: rect, mask: cg) // 乘以alpha
context.fill(rect)
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage }
else {
print("Failed to get current context or cgImage not exist")
return nil
}
}
}
let icon = image.reRender(with: .white)
searchBar.setImage(icon, for: .searchBar, state: .normal)
複製程式碼
2)獲取UI元件,更改其渲染模式
以修改放大鏡顏色為例。
這裡我們定義一個屬性,然後通過屬性監測器來應用到圖片上。這裡我們取的是在文章開頭定義的searchField
。然後取它的左檢視UIImageView
來修改。
public var leftIconColor: UIColor? {
didSet {
if let color = leftIconColor,
let iconView = searchField?.leftView as? UIImageView,
let icon = iconView.image {
iconView.image = icon.withRenderingMode(.alwaysTemplate)
iconView.tintColor = color
}
}
}
複製程式碼
可以通過獲取原圖片然後修改圖片的。
其它圖示的修改請參考文末附的原始碼。
2. 文字相關
這部分的設定都是跟UISearchField
的一樣
searchField?.textColor // 文字顏色
searchField?.font // 字型
searchField?.placeholder // 佔位符
searchField?.attributedPlaceholder // 富文字佔位符
複製程式碼
3. 游標顏色
通過設定searchField
的tintColor
即可修改游標顏色
修改searchBar
的tintColor
也可以達到效果,因為子檢視的tintColor
會自動繼承父級檢視。
但是設定searchBar
的tintColor
還會修改取消按鈕的顏色。如果你想要他們同一個顏色話,直接設定seachBar
更好。
4. 背景顏色
iOS11以下的直接設定searchField?.backgroundColor
即可。
而iOS11的要設定
let searchFieldBackgroudView = searchField?.subviews.first
searchFieldBackgroudView.backgroundColor
複製程式碼
二 取消按鈕
取消按鈕就是在輸入的時候顯示的cancel按鈕。只要設定showsCancelButton
即可。
searchBar.showsCancelButton = true
複製程式碼
因為模擬器預設語言都是英語的,所以你的取消按鈕預設也是顯示cancel。如果切換成中文的話顯示就是取消了
而如果要自定義這個按鈕的話,我們採用的也是遍歷子檢視獲取到這個按鈕的方法。
func setupCancelButton() {
for view in searchBar.subviews[0].subviews {
if view is UIButton { // 如果是UIButton
let button = view as! UIButton
//接下來就像普通button一樣設定就好了
button.setAttributedTitle(attributedTitle, for: .normal) // 通過設定副文字標題可以更改標題
break
}
}
}
複製程式碼
然後在searchBar
的代理事件的searchBarShouldBeginEditing
或者searchBarDidBeginEditing
中呼叫即可。
其它還有一些細節的設定可以參考下面的原始碼
原始碼已經提交到Github上了。
並且簡化了所有的屬性和代理方法。
歡迎大家來提交問題和分支。
如果覺得有幫助的話記得給顆星:P