当我开始输入自定义 UISearchBar 时,为什么我的 UITableView 没有出现?
Why isn't my UITableView appearing when I begin to type in the custom UISearchBar?
我正在尝试自定义 UISearchBar
,当用户开始输入时,UITableView
出现在 UISearchBar
下方;然而,现在当开始打字时,什么也没有出现。我添加了打印语句,它们正在打印更改后的文本。需要更改什么才能显示 UITableView
?
SuggestionSearchBar
import UIKit
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
init(del: UISearchBarDelegate, dropDownPossibilities: [String]) {
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
addSubview(suggestionTableView)
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: 300),
])
hideSuggestions()
}
func showSuggestions() {
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text!)
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text!)}
print(possibilities.count)
suggestionTableView.reloadData()
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
extension SuggestionSearchBar: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
}
ViewController
import UIKit
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"])
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
extension ViewController: UISearchBarDelegate {
func setUpSearchBar() {
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
navigationItem.titleView = searchBar
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print(searchBar.text!)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}
}
您有几个问题需要处理 -- 但要解决第一个问题:
“为什么我的 UITableView 没有出现...”
您正在添加一个 table 视图作为子视图,但是您显示它 在其父视图的边界 之外。
您可以通过将 table 视图的顶部约束更改为以下内容来轻松确认这一点:
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor, constant: -20.0),
当您现在开始在搜索字段中输入内容时,它会被 table 视图的顶部部分覆盖。
要显示 table 视图,您需要在 table 视图的父视图上禁用 .clipsToBounds
:
func showSuggestions() {
var sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
不过,下一个问题是您不能 select table 中的一行,因为它仍然在其父视图的范围之外。要处理这个问题,您需要实施 hitTest(...)
,但它会变得很复杂,因为 导航栏 获得命中,并且必须将命中传递给table.
编辑
对于更完整的示例...我将您的 SuggestionSearchBar
更改为包含 UISearchBar
和 UITableView
以及所有相关逻辑的 UIView
子类。
我在代码中添加了注释,应该 使一切都非常清楚。
要启用与存在于其父视图边界之外的元素的交互,您需要做的是在两者中覆盖hitTest(...)
导航栏和自定义标题视图。
完成这项工作的一种方法是使用子类 UINavigationBar
:
class CustomNavBar: UINavigationBar {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the titleView is not an instance of SuggestionSearchBarView
// just allow the default hitTest
guard let t = topItem, t.titleView is SuggestionSearchBarView else {
return super.hitTest(point, with: event)
}
// loop through subviews, checking hitTest until we find one
// this will allow tapping a view outside the bounds of this view
for v in self.subviews.reversed() {
if v.subviews.count > 0 {
for subv in v.subviews {
let p = subv.convert(point, from: self)
let r = subv.hitTest(p, with: event)
if r != nil {
return r
}
}
}
let p = v.convert(point, from: self)
let r = v.hitTest(p, with: event)
if r != nil {
return r
}
}
return nil
}
}
要在 Storyboard 中使用它,只需将导航控制器导航栏的自定义 Class 分配给 CustomNavBar
。
或者,如果您通过代码创建导航控制器:
let navigationController = UINavigationController(navigationBarClass: CustomNavBar.self, toolbarClass: nil)
你可以可能通过混合hitTest(...)
来做同样的事情,但这可能是一个更简单的方法。
这是修改后的 SuggestionSearchBar
(现在是 SuggestionSearchBarView
),以及相关的 UISearchBarDelegate
和 UITableViewDataSource, UITableViewDelegate
扩展:
class SuggestionSearchBarView: UIView {
var didSelect: ((String)->())?
var searchTapped: ((String)->())?
private let searchBar = UISearchBar()
private let suggestionTableView = UITableView()
private let tableHolderView = UIView()
public var allPossibilities: [String] = []
private var possibilities: [String] = []
private var svClips: Bool = true
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() -> Void {
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
searchBar.translatesAutoresizingMaskIntoConstraints = false
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
tableHolderView.translatesAutoresizingMaskIntoConstraints = false
addSubview(searchBar)
tableHolderView.addSubview(suggestionTableView)
addSubview(tableHolderView)
NSLayoutConstraint.activate([
searchBar.topAnchor.constraint(equalTo: topAnchor),
searchBar.leadingAnchor.constraint(equalTo: leadingAnchor),
searchBar.trailingAnchor.constraint(equalTo: trailingAnchor),
searchBar.bottomAnchor.constraint(equalTo: bottomAnchor),
// top and height constraints for tableHolderView
// leading/trailing will be set in didMoveToSuperview()
tableHolderView.topAnchor.constraint(equalTo: bottomAnchor),
tableHolderView.heightAnchor.constraint(equalToConstant: 300),
suggestionTableView.topAnchor.constraint(equalTo: tableHolderView.topAnchor),
suggestionTableView.leadingAnchor.constraint(equalTo: tableHolderView.leadingAnchor),
suggestionTableView.trailingAnchor.constraint(equalTo: tableHolderView.trailingAnchor),
suggestionTableView.bottomAnchor.constraint(equalTo: tableHolderView.bottomAnchor),
])
hideSuggestions()
// allows the tableView to show outside our bounds
clipsToBounds = false
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.setShowsCancelButton(true, animated: false)
searchBar.delegate = self
// some stylizing
suggestionTableView.backgroundColor = .white
suggestionTableView.layer.borderColor = UIColor.gray.cgColor
suggestionTableView.layer.borderWidth = 1.0
tableHolderView.layer.shadowColor = UIColor.black.cgColor
tableHolderView.layer.shadowRadius = 4
tableHolderView.layer.shadowOpacity = 0.6
tableHolderView.layer.shadowOffset = CGSize(width: 0, height: 2)
tableHolderView.layer.masksToBounds = false
}
override func didMoveToSuperview() {
if let sv = superview {
NSLayoutConstraint.activate([
// if we want the tableView width to match the searchField
//tableHolderView.leadingAnchor.constraint(equalTo: searchBar.searchTextField.leadingAnchor),
//tableHolderView.trailingAnchor.constraint(equalTo: searchBar.searchTextField.trailingAnchor),
// if we want the tableView to span the full view width
tableHolderView.leadingAnchor.constraint(equalTo: sv.leadingAnchor),
tableHolderView.trailingAnchor.constraint(equalTo: sv.trailingAnchor),
])
// save .clipsToBounds state of superview so we can
// restore it when hiding the table view
svClips = sv.clipsToBounds
}
}
func updateTable() -> Void {
let s = searchBar.text ?? ""
if s.isEmpty {
possibilities = allPossibilities
} else {
possibilities = allPossibilities.filter {[=14=].contains(s.lowercased())}
}
suggestionTableView.reloadData()
}
func showSuggestions() {
// we need to set .clipsToBounds = false on the superView
if let sv = superview {
sv.clipsToBounds = false
}
tableHolderView.isHidden = false
updateTable()
}
func hideSuggestions() {
// set .clipsToBounds on the superView
// back to its original state
if let sv = superview {
sv.clipsToBounds = svClips
}
tableHolderView.isHidden = true
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// loop through subviews, checking hitTest until we find one
// this will allow tapping a view outside the bounds of this view
for v in subviews.reversed() {
let p = v.convert(point, from: self)
let r = v.hitTest(p, with: event)
if r != nil {
return r
}
}
return nil
}
}
// MARK: searchBar Delegate funcs
extension SuggestionSearchBarView: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let s = searchBar.text ?? ""
print("Search Button Tapped:", s)
// use the closure to tell the controller that the Search button was tapped
searchTapped?(s)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
showSuggestions()
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
hideSuggestions()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateTable()
}
}
// MARK: tableView DataSource and Delegate funcs
extension SuggestionSearchBarView: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(white: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(white: 1.0, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected:", possibilities[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
endEditing(true)
// use the closure to tell the controller that a row was selected
didSelect?(possibilities[indexPath.row])
}
}
这是一个显示其用法的示例视图控制器:
class ViewController: UIViewController {
let searchBar = SuggestionSearchBarView()
override func viewDidLoad() {
super.viewDidLoad()
searchBar.translatesAutoresizingMaskIntoConstraints = false
// titleView width will be auto-sized by navigationBar,
// but only if wider than available space
// so, let's constrain the width to something like 10,000
// with less-than-required Priority
let c = searchBar.widthAnchor.constraint(equalToConstant: 10000)
c.priority = .defaultHigh
c.isActive = true
navigationItem.titleView = searchBar
// give the searchBar some suggested values
searchBar.allPossibilities = ["red", "green", "blue", "yellow"]
// assign a closure so we can take action when a
// suggestion is selected
searchBar.didSelect = { [weak self] str in
if let self = self {
let vc = UIViewController()
switch str {
case "red":
vc.view.backgroundColor = .red
case "green":
vc.view.backgroundColor = .green
case "blue":
vc.view.backgroundColor = .blue
case "yellow":
vc.view.backgroundColor = .yellow
default:
vc.view.backgroundColor = .white
}
self.navigationController?.pushViewController(vc, animated: true)
}
}
// assign a closure so we can take action when a
// the Search button is tapped
searchBar.searchTapped = { [weak self] str in
print("Search button was tapped....")
if let self = self {
// do something
}
}
}
}
请注意:这只是示例代码!!!试一试...如果它看起来可行对你来说,给它很多很多测试!
我正在尝试自定义 UISearchBar
,当用户开始输入时,UITableView
出现在 UISearchBar
下方;然而,现在当开始打字时,什么也没有出现。我添加了打印语句,它们正在打印更改后的文本。需要更改什么才能显示 UITableView
?
SuggestionSearchBar
import UIKit
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
init(del: UISearchBarDelegate, dropDownPossibilities: [String]) {
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
addSubview(suggestionTableView)
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: 300),
])
hideSuggestions()
}
func showSuggestions() {
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
@objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text!)
showSuggestions()
possibilities = allPossibilities.filter {[=10=].contains(searchBar.text!)}
print(possibilities.count)
suggestionTableView.reloadData()
}
@objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
extension SuggestionSearchBar: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
}
ViewController
import UIKit
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"])
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
extension ViewController: UISearchBarDelegate {
func setUpSearchBar() {
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
navigationItem.titleView = searchBar
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print(searchBar.text!)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}
}
您有几个问题需要处理 -- 但要解决第一个问题:
“为什么我的 UITableView 没有出现...”
您正在添加一个 table 视图作为子视图,但是您显示它 在其父视图的边界 之外。
您可以通过将 table 视图的顶部约束更改为以下内容来轻松确认这一点:
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor, constant: -20.0),
当您现在开始在搜索字段中输入内容时,它会被 table 视图的顶部部分覆盖。
要显示 table 视图,您需要在 table 视图的父视图上禁用 .clipsToBounds
:
func showSuggestions() {
var sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
不过,下一个问题是您不能 select table 中的一行,因为它仍然在其父视图的范围之外。要处理这个问题,您需要实施 hitTest(...)
,但它会变得很复杂,因为 导航栏 获得命中,并且必须将命中传递给table.
编辑
对于更完整的示例...我将您的 SuggestionSearchBar
更改为包含 UISearchBar
和 UITableView
以及所有相关逻辑的 UIView
子类。
我在代码中添加了注释,应该 使一切都非常清楚。
要启用与存在于其父视图边界之外的元素的交互,您需要做的是在两者中覆盖hitTest(...)
导航栏和自定义标题视图。
完成这项工作的一种方法是使用子类 UINavigationBar
:
class CustomNavBar: UINavigationBar {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the titleView is not an instance of SuggestionSearchBarView
// just allow the default hitTest
guard let t = topItem, t.titleView is SuggestionSearchBarView else {
return super.hitTest(point, with: event)
}
// loop through subviews, checking hitTest until we find one
// this will allow tapping a view outside the bounds of this view
for v in self.subviews.reversed() {
if v.subviews.count > 0 {
for subv in v.subviews {
let p = subv.convert(point, from: self)
let r = subv.hitTest(p, with: event)
if r != nil {
return r
}
}
}
let p = v.convert(point, from: self)
let r = v.hitTest(p, with: event)
if r != nil {
return r
}
}
return nil
}
}
要在 Storyboard 中使用它,只需将导航控制器导航栏的自定义 Class 分配给 CustomNavBar
。
或者,如果您通过代码创建导航控制器:
let navigationController = UINavigationController(navigationBarClass: CustomNavBar.self, toolbarClass: nil)
你可以可能通过混合hitTest(...)
来做同样的事情,但这可能是一个更简单的方法。
这是修改后的 SuggestionSearchBar
(现在是 SuggestionSearchBarView
),以及相关的 UISearchBarDelegate
和 UITableViewDataSource, UITableViewDelegate
扩展:
class SuggestionSearchBarView: UIView {
var didSelect: ((String)->())?
var searchTapped: ((String)->())?
private let searchBar = UISearchBar()
private let suggestionTableView = UITableView()
private let tableHolderView = UIView()
public var allPossibilities: [String] = []
private var possibilities: [String] = []
private var svClips: Bool = true
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() -> Void {
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
searchBar.translatesAutoresizingMaskIntoConstraints = false
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
tableHolderView.translatesAutoresizingMaskIntoConstraints = false
addSubview(searchBar)
tableHolderView.addSubview(suggestionTableView)
addSubview(tableHolderView)
NSLayoutConstraint.activate([
searchBar.topAnchor.constraint(equalTo: topAnchor),
searchBar.leadingAnchor.constraint(equalTo: leadingAnchor),
searchBar.trailingAnchor.constraint(equalTo: trailingAnchor),
searchBar.bottomAnchor.constraint(equalTo: bottomAnchor),
// top and height constraints for tableHolderView
// leading/trailing will be set in didMoveToSuperview()
tableHolderView.topAnchor.constraint(equalTo: bottomAnchor),
tableHolderView.heightAnchor.constraint(equalToConstant: 300),
suggestionTableView.topAnchor.constraint(equalTo: tableHolderView.topAnchor),
suggestionTableView.leadingAnchor.constraint(equalTo: tableHolderView.leadingAnchor),
suggestionTableView.trailingAnchor.constraint(equalTo: tableHolderView.trailingAnchor),
suggestionTableView.bottomAnchor.constraint(equalTo: tableHolderView.bottomAnchor),
])
hideSuggestions()
// allows the tableView to show outside our bounds
clipsToBounds = false
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.setShowsCancelButton(true, animated: false)
searchBar.delegate = self
// some stylizing
suggestionTableView.backgroundColor = .white
suggestionTableView.layer.borderColor = UIColor.gray.cgColor
suggestionTableView.layer.borderWidth = 1.0
tableHolderView.layer.shadowColor = UIColor.black.cgColor
tableHolderView.layer.shadowRadius = 4
tableHolderView.layer.shadowOpacity = 0.6
tableHolderView.layer.shadowOffset = CGSize(width: 0, height: 2)
tableHolderView.layer.masksToBounds = false
}
override func didMoveToSuperview() {
if let sv = superview {
NSLayoutConstraint.activate([
// if we want the tableView width to match the searchField
//tableHolderView.leadingAnchor.constraint(equalTo: searchBar.searchTextField.leadingAnchor),
//tableHolderView.trailingAnchor.constraint(equalTo: searchBar.searchTextField.trailingAnchor),
// if we want the tableView to span the full view width
tableHolderView.leadingAnchor.constraint(equalTo: sv.leadingAnchor),
tableHolderView.trailingAnchor.constraint(equalTo: sv.trailingAnchor),
])
// save .clipsToBounds state of superview so we can
// restore it when hiding the table view
svClips = sv.clipsToBounds
}
}
func updateTable() -> Void {
let s = searchBar.text ?? ""
if s.isEmpty {
possibilities = allPossibilities
} else {
possibilities = allPossibilities.filter {[=14=].contains(s.lowercased())}
}
suggestionTableView.reloadData()
}
func showSuggestions() {
// we need to set .clipsToBounds = false on the superView
if let sv = superview {
sv.clipsToBounds = false
}
tableHolderView.isHidden = false
updateTable()
}
func hideSuggestions() {
// set .clipsToBounds on the superView
// back to its original state
if let sv = superview {
sv.clipsToBounds = svClips
}
tableHolderView.isHidden = true
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// loop through subviews, checking hitTest until we find one
// this will allow tapping a view outside the bounds of this view
for v in subviews.reversed() {
let p = v.convert(point, from: self)
let r = v.hitTest(p, with: event)
if r != nil {
return r
}
}
return nil
}
}
// MARK: searchBar Delegate funcs
extension SuggestionSearchBarView: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let s = searchBar.text ?? ""
print("Search Button Tapped:", s)
// use the closure to tell the controller that the Search button was tapped
searchTapped?(s)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
showSuggestions()
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
hideSuggestions()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateTable()
}
}
// MARK: tableView DataSource and Delegate funcs
extension SuggestionSearchBarView: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(white: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(white: 1.0, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected:", possibilities[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
endEditing(true)
// use the closure to tell the controller that a row was selected
didSelect?(possibilities[indexPath.row])
}
}
这是一个显示其用法的示例视图控制器:
class ViewController: UIViewController {
let searchBar = SuggestionSearchBarView()
override func viewDidLoad() {
super.viewDidLoad()
searchBar.translatesAutoresizingMaskIntoConstraints = false
// titleView width will be auto-sized by navigationBar,
// but only if wider than available space
// so, let's constrain the width to something like 10,000
// with less-than-required Priority
let c = searchBar.widthAnchor.constraint(equalToConstant: 10000)
c.priority = .defaultHigh
c.isActive = true
navigationItem.titleView = searchBar
// give the searchBar some suggested values
searchBar.allPossibilities = ["red", "green", "blue", "yellow"]
// assign a closure so we can take action when a
// suggestion is selected
searchBar.didSelect = { [weak self] str in
if let self = self {
let vc = UIViewController()
switch str {
case "red":
vc.view.backgroundColor = .red
case "green":
vc.view.backgroundColor = .green
case "blue":
vc.view.backgroundColor = .blue
case "yellow":
vc.view.backgroundColor = .yellow
default:
vc.view.backgroundColor = .white
}
self.navigationController?.pushViewController(vc, animated: true)
}
}
// assign a closure so we can take action when a
// the Search button is tapped
searchBar.searchTapped = { [weak self] str in
print("Search button was tapped....")
if let self = self {
// do something
}
}
}
}
请注意:这只是示例代码!!!试一试...如果它看起来可行对你来说,给它很多很多测试!