I embedded a tableView to the superview of a Custom UITextfield. The tableview is to display results on the view which means I want to be able to scroll and select a cell in the tableView. The tableview shows but I am unable to scroll or select the tableView cell.
Here is how the tableView is rendered with the UITexfield.
UITexfield extended
override init(frame: CGRect) {
super.init(frame: frame)
shared()
commonInit()
if let superview = superview {
setupAutocompleteTable(superview)
}
}
public override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
commonInit()
setupAutocompleteTable(newSuperview!)
}
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = autoCompleteCellHeight
tableView.isHidden = hidesWhenEmpty ?? true
tableView.layer.borderColor = UIColor.lightGray.cgColor
tableView.layer.borderWidth = 0.5
tableView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
return tableView
}()
fileprivate func setupAutocompleteTable(_ view: UIView) {
autoCompleteTableMargin = 10.0
view.addSubview(tableView)
tableView.topAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
tableView.heightAnchor.constraint(equalToConstant: 30).isActive = true
autoCompleteTableView = tableView
autoCompleteTableHeight = 200.0
}
the ViewController
lazy var searchField: GooglePlaceSearchField = {
let field = GooglePlaceSearchField()
field.translatesAutoresizingMaskIntoConstraints = true
field.placeholder = "Enter area, city .."
field.setIcon(#imageLiteral(resourceName: "zamasearch"))
field.highLightTypeTextedEnabled = true
return field
}()
view.addSubview(searchBgView)
searchBgView.addSubview(searchField)
any help on how to interact with the tableView
constraints of the searchField
searchBgView.anchor(top: view.safeAreaLayoutGuide.topAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 14, paddingLeft: 20, paddingBottom: 0, paddingRight: 20, width: 0, height: 50, enableInsets: false)
searchField.anchor(top: searchBgView.topAnchor, left: searchBgView.leftAnchor, bottom: searchBgView.bottomAnchor, right: iconContainerView.leftAnchor, paddingTop: 00, paddingLeft: 20, paddingBottom: 0, paddingRight: 0, width: 0, height: 0, enableInsets: false)
Edit:
After re-reading the question and following comments, the tableView was being added as a sibling to the textField... the same issue applies though. The tableView is outside the bounds of its superview.
This example can still be used as a starting point for handling the hit-testing inside the "search background view" (or, use the table as a subview of the field as shown here).
Here's a quick example which you should be able to use as a base for your custom field / data source.
If you comment-out the hitTest(...)
func, you'll see the table but won't be able to interact with it.
Note: This is just example code to get you on your way -- not to be considered production-ready.
class MyCustomTextField: UITextField {
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.dataSource = self
tableView.delegate = self
tableView.layer.borderColor = UIColor.lightGray.cgColor
tableView.layer.borderWidth = 0.5
tableView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
return tableView
}()
let theData = [ "A", "B", "C", "D", "E", "F", "G", "H", "I" ]
// if we comment-out this func, we will NOT be able to interact with the tableView
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }
guard !isHidden else { return nil }
guard alpha >= 0.01 else { return nil }
let convertedPoint = tableView.convert(point, from: self)
if let v = tableView.hitTest(convertedPoint, with: event) {
return v
}
guard self.point(inside: point, with: event) else { return nil }
return self
}
override init(frame: CGRect) {
super.init(frame: frame)
setupAutocompleteTable(self)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
setupAutocompleteTable(self)
}
fileprivate func setupAutocompleteTable(_ view: UIView) {
if tableView.superview == nil {
view.addSubview(tableView)
tableView.topAnchor.constraint(equalTo: view.bottomAnchor, constant: 20).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView.heightAnchor.constraint(equalToConstant: 200).isActive = true
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TheCell")
}
}
}
extension MyCustomTextField: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TheCell", for: indexPath)
cell.textLabel?.text = theData[indexPath.row]
return cell
}
}
extension MyCustomTextField: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.text = theData[indexPath.row]
}
}
class TextFieldSubViewController: UIViewController {
let customTextField: MyCustomTextField = {
let v = MyCustomTextField()
v.translatesAutoresizingMaskIntoConstraints = false
v.borderStyle = .roundedRect
v.backgroundColor = .yellow // makes it easy to see
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(customTextField)
NSLayoutConstraint.activate([
customTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
customTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
customTextField.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),
])
}
}
Result:
Edit 2:
Here's another quick example, using a "search background view" with UITextField
, UIButton
and UITableView
as subviews (siblings of each other). The table view will show / hide when the text field Begins / Ends editing.
class CustomSearchView: UIView {
lazy var theTextField: UITextField = {
let v = UITextField()
v.translatesAutoresizingMaskIntoConstraints = false
v.borderStyle = .roundedRect
v.delegate = self
return v
}()
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.dataSource = self
tableView.delegate = self
tableView.layer.borderColor = UIColor.lightGray.cgColor
tableView.layer.borderWidth = 0.5
tableView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
return tableView
}()
let doneButton: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.setTitle("Done", for: .normal)
v.setTitleColor(.blue, for: .normal)
return v
}()
let theData = [ "A", "B", "C", "D", "E", "F", "G", "H", "I" ]
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
addSubview(theTextField)
addSubview(doneButton)
addSubview(tableView)
NSLayoutConstraint.activate([
doneButton.topAnchor.constraint(equalTo: topAnchor, constant: 4.0),
doneButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4.0),
doneButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8.0),
theTextField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8.0),
theTextField.trailingAnchor.constraint(equalTo: doneButton.leadingAnchor, constant: -8.0),
theTextField.centerYAnchor.constraint(equalTo: doneButton.centerYAnchor),
tableView.topAnchor.constraint(equalTo: theTextField.bottomAnchor, constant: 8.0),
tableView.leadingAnchor.constraint(equalTo: theTextField.leadingAnchor, constant: 0.0),
tableView.trailingAnchor.constraint(equalTo: theTextField.trailingAnchor, constant: 0.0),
tableView.heightAnchor.constraint(equalToConstant: 200.0),
])
doneButton.setContentHuggingPriority(.required, for: .horizontal)
doneButton.addTarget(self, action: #selector(doneTapped), for: .touchUpInside)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TheCell")
tableView.isHidden = true
}
@objc func doneTapped() -> Void {
self.endEditing(true)
}
// if we comment-out this func, we will NOT be able to interact with the tableView
// Note: this hitTest func based on source here: http://khanlou.com/2018/09/hacking-hit-tests/
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }
guard !isHidden else { return nil }
guard alpha >= 0.01 else { return nil }
for subview in subviews.reversed() {
let convertedPoint = subview.convert(point, from: self)
if let candidate = subview.hitTest(convertedPoint, with: event) {
return candidate
}
}
guard self.point(inside: point, with: event) else { return nil }
return self
}
}
extension CustomSearchView: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
tableView.isHidden = false
}
func textFieldDidEndEditing(_ textField: UITextField) {
tableView.isHidden = true
}
}
extension CustomSearchView: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TheCell", for: indexPath)
cell.textLabel?.text = theData[indexPath.row]
return cell
}
}
extension CustomSearchView: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.theTextField.text = theData[indexPath.row]
}
}
class TextFieldSubViewController: UIViewController {
let customSearchView: CustomSearchView = {
let v = CustomSearchView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .lightGray
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(customSearchView)
NSLayoutConstraint.activate([
customSearchView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0),
customSearchView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0.0),
customSearchView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0),
])
}
}
Result:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.