效果图
XLSearchViewController.swift
import UIKit
import YYCache
enum XLSearchType:Int {
///健康百科
case healthyWiki = 1
}
class XLSearchViewController: BaseViewController {
var cellWidth = SCREEN_WIDTH/2
var historyArr : Array = []
//默认搜索健康百科
var placehoder = ""
var searchType:XLSearchType = .healthyWiki
var cacheName = NSCacheModuleKeys.searchHistory_wiki_info.rawValue
override func viewDidLoad() {
super.viewDidLoad()
getSearchHistory()
createUI()
viewBlocks()
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
lazy var searchHeaderView:XLSearchHeaderView = {
let view = XLSearchHeaderView.init(placehoder: placehoder)
return view
}()
lazy var historyLabel: UILabel = {
let label = UILabel.labelWithTitle(text: "搜索历史",
textColor: CNaviItemDisableColor,
textFont: 12,
textAlignment: .left, specialFont: nil)
return label
}()
lazy var clearBut: UIButton = {
let but = UIButton.buttonWithImage(title: nil, normalImage: R.image.search_clear_history()!, highlightImage: nil, selectedImage: nil)
but.addTarget(self, action: #selector(clearAction), for: .touchUpInside)
return but
}()
lazy var historyCollectionView: UICollectionView = {
let collectV = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: historyCollectionViewFlowLayout)
collectV.delegate = self
collectV.dataSource = self
collectV.isScrollEnabled = false
collectV.register(XLSearchHistoryCollectionViewCell.self, forCellWithReuseIdentifier: "XLSearchHistoryCollectionViewCell")
collectV.backgroundColor = CViewBGColor
return collectV
}()
lazy var historyCollectionViewFlowLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout.init()
layout.itemSize = CGSize(width: cellWidth, height: 34)
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .vertical
layout.sectionInset = UIEdgeInsets.init(top: 0, left: 0, bottom: 0, right: 0)
return layout
}()
func createUI() {
view.addSubview(searchHeaderView)
view.addSubview(historyLabel)
view.addSubview(clearBut)
view.addSubview(historyCollectionView)
searchHeaderView.snp.makeConstraints { make in
make.left.top.right.equalTo(self.view)
make.height.equalTo(StatusBarHeight + 56)
}
historyLabel.snp.makeConstraints { make in
make.left.equalTo(15)
make.top.equalTo(searchHeaderView.snp.bottom).offset(15)
}
clearBut.snp.makeConstraints { make in
make.centerY.equalTo(historyLabel)
make.right.equalTo(-15)
make.width.height.equalTo(20)
}
historyCollectionView.snp.makeConstraints { make in
make.left.equalTo(0)
make.right.equalTo(0)
make.top.equalTo(historyLabel.snp.bottom).offset(12)
make.height.equalTo(136)
}
}
func viewBlocks() {
}
@objc func clearAction() {
XLAlertTool.showAlert(title: "您确定清空搜索历史?", messgae: "", items: ["取消", "确定"], haveCancel: false) {[weak self] (str, index) in
if index == 1 {
let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
cache?.removeObject(forKey: self?.cacheName ?? "")
self?.historyArr = []
self?.historyCollectionView.reloadData()
}
}
}
//获取本地历史数据
func getSearchHistory() {
//获取搜索历史cache
let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
//获取搜索历史与wiki相关cache
historyArr = cache?.object(forKey: cacheName) as? Array ?? []
}
//处理本地缓存历史记录
func saveSearchHistory(searchStr:String) {
//获取搜索历史cache
let cache = YYCache.init(name: NSCacheModuleKeys.searchHistory_info.rawValue)
//删除历史数据有该数据的记录
historyArr.removeAll(where: {$0 == searchStr})
//将搜索记录插入第一个下标位置
historyArr.insert(searchStr, at: 0)
//若大于8个记录,删除最后一个
if historyArr.count > 8 {
historyArr.removeLast()
}
cache?.setObject(historyArr as NSCoding, forKey: cacheName)
self.historyCollectionView.reloadData()
}
}
extension XLSearchViewController:UICollectionViewDelegate,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return historyArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:XLSearchHistoryCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "XLSearchHistoryCollectionViewCell", for: indexPath) as! XLSearchHistoryCollectionViewCell
cell.textLabel.text = historyArr[indexPath.row]
cell.lineLabel.isHidden = indexPath.row%2 == 0
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
searchHeaderView.searchTextField.text = historyArr[indexPath.row]
if let block = searchHeaderView.searchCompletion {
block(historyArr[indexPath.row])
}
searchHeaderView.searchTextField.resignFirstResponder()
}
}
XLSearchHistoryCollectionViewCell.swift
import UIKit
class XLSearchHistoryCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.createUI()
}
func createUI() {
self.backgroundColor = CViewBGColor
self.contentView.addSubview(textLabel)
self.contentView.addSubview(lineLabel)
textLabel.snp.makeConstraints { make in
make.top.right.bottom.equalTo(self.contentView)
make.left.equalTo(lineLabel.snp.right).offset(15)
}
lineLabel.snp.makeConstraints { make in
make.centerY.left.equalTo(self.contentView)
make.width.equalTo(1)
make.height.equalTo(10)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var backView: UIView = {
let view = UIView()
view.backgroundColor = CSystemMsgBGColor
view.alpha = 0.2
return view
}()
lazy var textLabel: UILabel = {
let label = UILabel.labelWithTitle(text: nil,
textColor: CTextMainColor,
textFont: 16,
textAlignment: .left, specialFont: nil)
return label
}()
lazy var lineLabel: UILabel = {
let label = UILabel.labelWithTitle(text: nil,
textColor: CTextMainColor,
textFont: 16,
textAlignment: .left, specialFont: nil)
label.backgroundColor = CSeparator2Color
return label
}()
}
XLSearchHeaderView.swift
import UIKit
class XLSearchHeaderView: UIView {
var placeholderStr :String?
var cancelSearchCompletion: (() -> ())?
var clearSearchStrCompletion: (() -> ())?
var searchCompletion: ((_ text:String) -> ())?
deinit {
}
override init(frame: CGRect) {
super.init(frame: frame)
}
init(placehoder:String) {
self.init()
self.placeholderStr = placehoder
self.setupSubview()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupSubview() {
addSubview(searchTextView)
searchTextView.addSubview(iconImageView)
searchTextView.addSubview(searchTextField)
addSubview(cancelBut)
searchTextView.snp.makeConstraints { make in
make.left.equalTo(10)
make.right.equalTo(-52)
make.height.equalTo(40)
make.centerY.equalTo(cancelBut)
}
iconImageView.snp.makeConstraints { make in
make.left.equalTo(18)
make.width.height.equalTo(20)
make.centerY.equalTo(searchTextView)
}
searchTextField.snp.makeConstraints { make in
make.left.equalTo(iconImageView.snp.right).offset(12)
make.centerY.equalTo(searchTextView)
make.right.equalTo(searchTextView.snp.right).offset(-18)
}
cancelBut.snp.makeConstraints { make in
make.right.equalTo(-10)
make.top.equalTo(StatusBarHeight + 19)
make.width.equalTo(32)
make.height.equalTo(22)
}
}
lazy var searchTextView:UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.masksToBounds = true
view.layer.cornerRadius = 20
return view
}()
lazy var iconImageView:UIImageView = {
let view = UIImageView()
view.image = R.image.wiki_search()
return view
}()
lazy var searchTextField:UITextField = {
let textField = UITextField()
textField.placeholder = placeholderStr
textField.font = UIFont.normalFont(fontSize: 16)
textField.textColor = CTextMainColor
textField.delegate = self
textField.returnKeyType = .search
textField.clearButtonMode = .whileEditing
textField.addTarget(self, action: #selector(changeText(_:)), for: .editingChanged)
return textField
}()
lazy var cancelBut: UIButton = {
let but = UIButton.buttonWithTitle(title: "取消", titleFont: 16, normalTitleColor: CTextMainColor, backgroundColor: nil)
but.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
return but
}()
@objc func cancelAction() {
self.cancelSearchCompletion != nil ? self.cancelSearchCompletion!() : nil
}
}
extension XLSearchHeaderView:UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard textField.text?.count ?? 0 > 0 else {
return true
}
if let block = searchCompletion {
block(textField.text ?? "")
}
textField.resignFirstResponder()
return true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
self.clearSearchStrCompletion != nil ? self.clearSearchStrCompletion!() : nil
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.searchTextField.perform(#selector(selectAll(_:)), with: nil, afterDelay: 0.0)
}
@objc func changeText(_ textField: UITextField) {
guard textField.text?.count ?? 0 > 0 else {
self.clearSearchStrCompletion != nil ? self.clearSearchStrCompletion!() : nil
return
}
let range = textField.markedTextRange
if range == nil {
if let block = searchCompletion {
block(textField.text ?? "")
}
}
}
}
以下为引用
XLSearchWikiViewController.swift
import UIKit
class XLSearchWikiViewController: XLSearchViewController,PushWebProtocol {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
required init(params: Dictionary?) {
super.init(params: nil)
placehoder = "请输入文章标题"
searchType = .healthyWiki
cacheName = NSCacheModuleKeys.searchHistory_wiki_info.rawValue
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewBlocks() {
//取消
searchHeaderView.cancelSearchCompletion = {[weak self] in
self?.navigationController?.popViewController(animated: false)
}
//clear
searchHeaderView.clearSearchStrCompletion = {[weak self] in
self?.viewModel.dataArray = []
self?.tableView.reloadData()
self?.searchViewStyle(isSearching: false)
}
//搜索
searchHeaderView.searchCompletion = {[weak self] searchStr in
//保存历史记录
self?.saveSearchHistory(searchStr: searchStr)
//调接口获取数据
self?.viewModel.getWikiSearchData(searchStr: searchStr)
}
viewModel.reloadDataSuccess = {[weak self] in
self?.searchViewStyle(isSearching: true)
if (self?.viewModel.dataArray.isEmpty)! {
self?.tableView.emptyView = XLEmptyView.init(type: .wiki_search_empty, offset: -150, tapClosure: { [weak self] in
self?.searchHeaderView.searchTextField.resignFirstResponder()
self?.viewModel.getWikiSearchData(searchStr: self?.searchHeaderView.searchTextField.text ?? "")
})
}
self?.tableView.reloadData()
}
}
private lazy var tableView: UITableView = {
let tableView = UITableView.init(delegate: self, dataSource: self)
tableView.mj_header = viewModel.headerRefresh
tableView.mj_footer = viewModel.footerRefresh
tableView.backgroundColor = .clear
return tableView
}()
lazy var viewModel: XLHealthyWikiViewModel = {
let model = XLHealthyWikiViewModel.init()
return model
}()
func setupUI() {
view.addSubview(tableView)
self.tableView.frame = CGRect.zero
}
//当前页面状态ture:搜索结果;false:未开始搜索
func searchViewStyle(isSearching:Bool) {
self.historyLabel.isHidden = isSearching
self.clearBut.isHidden = isSearching
self.historyCollectionView.isHidden = isSearching
self.tableView.isHidden = !isSearching
if isSearching {
tableView.snp.updateConstraints { make in
make.top.equalTo(searchHeaderView.snp.bottom).offset(6)
make.left.right.bottom.equalTo(view)
}
} else {
self.tableView.frame = CGRect.zero
}
}
}
//MARK: - UITableViewDelegate
extension XLSearchWikiViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.dataArray.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = viewModel.dataArray[indexPath.row]
let searchStr = searchHeaderView.searchTextField.text ?? ""
let cell = XLWikiSearchTableViewCell.cell(of: tableView, indexPath, viewModel.dataArray[indexPath.row])
cell.titleLabel.attributedText = model?.title?.m_setKeyColorAll(keyString: [searchStr], keyColor: CRedTipColor)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
saveSearchHistory(searchStr: searchHeaderView.searchTextField.text ?? "")
let model = viewModel.dataArray[indexPath.row]
self.pushWeb(url: model?.wiki_h5_url ?? "", type: XLWebType.wikiDetail, para: nil)
}
}