iOS UISearchController樣式全面設定

NDaoxS發表於2018-08-15

iOS UISearchController樣式全面設定

Q: 如果想要做到上圖所示的搜尋框需要怎麼設定?

搜尋框的樣式設定都是基於UISearchControllersearchBar也就是UISearchBar設定的。 但是UISearchBar並沒有提供多少自定義設定。 圖示相關的設定也主要是系統提供的幾種簡單樣式。

而iOS11和iOS11以下的搜尋框由於樣式不一樣,很多屬性的設定不盡相同。

所以這篇文章就是對怎麼修改UISearchController樣式的梳理

首先UISearchController主要是對UISearchBar的封裝,而UISearchBar又包含了UITextFieldUINavigationButton(取消按鈕)

一 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. 游標顏色

通過設定searchFieldtintColor即可修改游標顏色
修改searchBartintColor也可以達到效果,因為子檢視的tintColor會自動繼承父級檢視。
但是設定searchBartintColor還會修改取消按鈕的顏色。如果你想要他們同一個顏色話,直接設定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

相關文章