iOS: 熱門搜尋標籤介面(Swift3)
阿新 • • 發佈:2018-12-23
首先建立一個SearchView類,這個類分為上面的標題文字和下面的按鈕.按鈕的數量是不確定的,在將按鈕新增到SearchView之前先記錄下這個按鈕的maxX加上橫向間距的值和y值,在佈局下一個按鈕的時候先判斷這一行餘下的距離是否大於這個按鈕的寬度,也就是SearchView檢視的寬度減去上一個按鈕的maxX加上橫向間距的值是否大於這個按鈕的寬度.如果大於就是說剩下的距離可以放下這個按鈕,那麼這個按鈕的x值就是上一個按鈕的maxX加上橫向間距,y值與上一個按鈕相同;如果小於就是說剩下的距離放不下這個按鈕,那麼就將這個按鈕放到下一行,這個按鈕的x值就是0,y值就是上一個按鈕的y值加上縱向間距和按鈕的高度.整個SearchView檢視的高度是最後一個按鈕的maxY.
class SearchView: UIView {
//標題
private let titleLabel = UILabel()
//上一個按鈕的maxX加上間距
private var lastX: CGFloat = 0
//上一個按鈕的y值
private var lastY: CGFloat = 35
//按鈕的回撥block
private var btnCallBackBlock: ((_ btn: UIButton) -> ())?
//SearchView的總高度
var searchViewHeight: CGFloat = 0
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel.frame = CGRect(x: 0, y: 0, width: frame.size.width - 30, height: 35)
titleLabel.font = UIFont.systemFont(ofSize: 15)
titleLabel.textColor = UIColor(red: 140 / 255.0, green: 140 / 255.0, blue: 140 / 255.0, alpha: 1 )
addSubview(titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(frame: CGRect, titleLabelText: String, btnTexts: [String], btnCallBackBlock: @escaping ((_ sender: UIButton) -> ())) {
self.init(frame: frame)
titleLabel.text = titleLabelText
//按鈕文字的寬度
var btnW: CGFloat = 0
//按鈕的高度
let btnH: CGFloat = 30
//文字與按鈕兩邊的距離之和
let addW: CGFloat = 30
//橫向間距
let marginX: CGFloat = 10
//縱向間距
let marginY: CGFloat = 10
for i in 0..<btnTexts.count {
let btn = UIButton(type: .custom)
btn.setTitle(btnTexts[i], for: .normal)
btn.setTitleColor(UIColor.black, for: .normal)
btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
btn.titleLabel?.sizeToFit()
btn.backgroundColor = UIColor.white
btn.layer.cornerRadius = 15
btn.layer.masksToBounds = true
btn.layer.borderWidth = 0.5
btn.layer.borderColor = UIColor(red: 200 / 255.0, green: 200 / 255.0, blue: 200 / 255.0, alpha: 1).cgColor
btn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
//按鈕的總寬度
btnW = (btn.titleLabel?.bounds.width)! + addW
//在給按鈕的frame賦值之前先判斷本行餘下的寬度是否大於將要佈局的按鈕的寬度,如果大於則x值為上一個按鈕的寬度加上橫向間距,y值與上一個按鈕相同,如果小於則x值為0,y值為上一個按鈕的y值加上按鈕的高度和縱向間距
if frame.width - lastX > btnW {
btn.frame = CGRect(x: lastX, y: lastY, width: btnW, height: btnH)
} else {
btn.frame = CGRect(x: 0, y: lastY + marginY + btnH, width: btnW, height: btnH)
}
lastX = btn.frame.maxX + marginX
lastY = btn.frame.origin.y
searchViewHeight = btn.frame.maxY
addSubview(btn)
}
self.btnCallBackBlock = btnCallBackBlock
}
@objc private func btnClick(sender: UIButton) {
btnCallBackBlock!(sender)
}
}
點選熱門搜尋檢視的按鈕會發生四件事: 1.將按鈕文字顯示到搜尋框 2.將按鈕文字寫入到偏好設定 3.在歷史記錄中顯示按鈕 4.更新清空歷史按鈕的狀態
常量
let UIScreenBounds: CGRect = UIScreen.main.bounds
let KNavigationBarBackgroundColor = UIColor(red: 249 / 255.0, green: 250 / 255.0, blue: 253 / 255.0, alpha: 1)
let KGlobalBackgroundColor = UIColor(red: 239 / 255.0, green: 239 / 255.0, blue: 239 / 255.0, alpha: 1)
let HistorySearch = "HistorySearch"
把ScrollView新增到檢視中
private func setup() { navigationController?.navigationBar.barTintColor = KNavigationBarBackgroundColor
view.backgroundColor = KGlobalBackgroundColor
view.addSubview(scrollView)
scrollView.addSubview(cleanHistoryButton)
}
lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView(frame: UIScreen.main.bounds)
scrollView.alwaysBounceVertical = true
scrollView.backgroundColor = UIColor(red: 239 / 255.0, green: 239 / 255.0, blue: 239 / 255.0, alpha: 1)
scrollView.delegate = self
return scrollView
}()
搜尋框
lazy var searchBar: UISearchBar = {
let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width * 0.9, height: 30))
searchBar.placeholder = "請輸入商品名稱"
searchBar.barTintColor = UIColor.white
searchBar.keyboardType = .default
searchBar.delegate = self
return searchBar
}()
//SearchBar代理方法
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if (searchBar.text?.characters.count)! > 0 {
//將搜尋框文字寫入到偏好設定
writeHistorySearchToUserDefaults(str: searchBar.text!)
}
}
private func setupTilteView() {
let bgView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreenBounds.width, height: 30))
bgView.backgroundColor = UIColor.white
bgView.layer.masksToBounds = true
bgView.layer.cornerRadius = 6
bgView.layer.borderColor = UIColor(red: 100 / 255.0, green: 100 / 255.0, blue: 100 / 255.0, alpha: 1).cgColor
bgView.layer.borderWidth = 0.2
UIGraphicsBeginImageContext(bgView.bounds.size)
bgView.layer.render(in: UIGraphicsGetCurrentContext()!)
let bgImage = UIGraphicsGetImageFromCurrentImageContext()
searchBar.setSearchFieldBackgroundImage(bgImage, for: .normal)
navigationItem.titleView = searchBar
}
熱門搜尋檢視
var hotSearchView: SearchView?
private func setupHotSearchView() {
//如果偏好設定為空寫入一個空陣列
var historySearch = UserDefaults.standard.object(forKey: HistorySearch) as? [String]
if historySearch == nil {
historySearch = [String]()
UserDefaults.standard.set(historySearch, forKey: HistorySearch)
}
//標籤的標題 可以從伺服器獲得
let arr = ["年貨大集", "酸奶", "水", "車釐子", "洽洽瓜子", "維他", "香菸", "周黑鴨", "草莓", "星巴克", "滷味"]
hotSearchView = SearchView(frame: CGRect(x: 10, y: 40, width: UIScreenBounds.width - 20, height: 100), titleLabelText: "熱門搜尋", btnTexts: arr, btnCallBackBlock: { [weak self](btn) in
let str = btn.title(for: .normal)
//將按鈕文字顯示到搜尋框
self?.searchBar.text = str
//將按鈕文字寫入到偏好設定 self?.writeHistorySearchToUserDefaults(str: str!)
})
hotSearchView?.bounds.size.height = (hotSearchView?.searchViewHeight)!
scrollView.addSubview(hotSearchView!)
}
將歷史搜尋寫入到偏好設定
//將歷史搜尋寫入偏好設定
private func writeHistorySearchToUserDefaults(str: String) {
//從偏好設定中讀取
var historySearch = UserDefaults.standard.object(forKey: HistorySearch) as? [String]
//如果已經存在就不重複寫入
for text in historySearch! {
if text == str {
return
}
}
historySearch!.append(str)
UserDefaults.standard.set(historySearch, forKey: HistorySearch)
setupHistorySearchView()
}
歷史記錄檢視
var historySearchView: SearchView?
private func setupHistorySearchView() {
if historySearchView != nil {
historySearchView?.removeFromSuperview()
historySearchView = nil
}
//從偏好設定中讀取
let arr = UserDefaults.standard.object(forKey: HistorySearch) as! [String]
if arr.count > 0 {
historySearchView = SearchView(frame: CGRect(x: 10, y: (hotSearchView?.frame.maxY)! + 20, width: UIScreenBounds.width - 20, height: 0), titleLabelText: "歷史記錄", btnTexts: arr, btnCallBackBlock: { [weak self](btn) in
let str = btn.title(for: .normal)
self?.searchBar.text = str
})
historySearchView?.frame.size.height = (historySearchView?.searchViewHeight)!
scrollView.addSubview(historySearchView!)
updateCleanHistoryButton(hidden: false)
}
}
更新清空歷史檢視狀態
private func updateCleanHistoryButton(hidden: Bool) {
if historySearchView != nil {
cleanHistoryButton.frame = CGRect(x: 0.1 * UIScreenBounds.width, y: (historySearchView?.frame.maxY)! + 20, width: UIScreenBounds.width * 0.8, height: 40)
}
cleanHistoryButton.isHidden = hidden
}
清空歷史按鈕
lazy var cleanHistoryButton: UIButton = {
let cleanHistoryButton = UIButton(type: .custom)
cleanHistoryButton.setTitle("清 空 歷 史", for: .normal)
cleanHistoryButton.setTitleColor(UIColor(red: 153 / 255.0, green: 153 / 255.0, blue: 153 / 255.0, alpha: 1), for: .normal)
cleanHistoryButton.titleLabel?.font = UIFont.systemFont(ofSize: 14)
cleanHistoryButton.backgroundColor = UIColor(red: 239 / 255.0, green: 239 / 255.0, blue: 239 / 255.0, alpha: 1)
cleanHistoryButton.layer.cornerRadius = 5
cleanHistoryButton.layer.borderColor = UIColor(red: 200 / 255.0, green: 200 / 255.0, blue: 200 / 255.0, alpha: 1).cgColor
cleanHistoryButton.layer.borderWidth = 0.5
cleanHistoryButton.isHidden = true
cleanHistoryButton.addTarget(self, action: #selector(cleanHistory), for: .touchUpInside)
return cleanHistoryButton
}()
@objc private func cleanHistory() {
var historys = UserDefaults.standard.object(forKey: HistorySearch) as? [String]
historys?.removeAll()
UserDefaults.standard.set(historys, forKey: HistorySearch)
setupHistorySearchView()
updateCleanHistoryButton(hidden: true)
}