Created
June 25, 2019 10:21
-
-
Save AdieOlami/201ddb5b99c08a5f1316b0b91b9b994a to your computer and use it in GitHub Desktop.
GooglePlace Autocomplete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import GooglePlaces | |
class PlaceSearchField: UITextField, UITextFieldDelegate { | |
//MARK: - PROPERTIES | |
/// Instance of autoCompleteTableView | |
fileprivate var autoCompleteTableView: UITableView? | |
/// Gives the array of autoCompletePlacesData | |
open var autoCompletePlacesData = [String]() | |
/// Gives the selected place and indexPath | |
open var selectedPlace: ((String, IndexPath) -> Void)? | |
/// Font for the places data | |
open var autoCompleteTextFont = UIFont.systemFont(ofSize: 12) | |
/// Color of the places data | |
open var autoCompleteTextColor = UIColor.black | |
/// Used to set the height of cell for each suggestions | |
open var autoCompleteCellHeight: CGFloat = 44.0 | |
/// The maximum visible suggestion | |
open var maxAutoCompleteDataCount = 5 | |
/// Used to set your own preferred separator inset | |
open var autoCompleteSeparatorInset = UIEdgeInsets.zero | |
/// Hides autoCompleteTableView after selecting a place | |
open var hidesWhenSelected = true | |
/// Shows autoCompletePlacesData with formatting | |
open var highLightTypeTextedEnabled: Bool? | |
/// Define attributes for highlighted text | |
open var highLightTypeTextedAttributes: [NSAttributedString.Key: Any]? | |
/// Hides autoCompleteTableView when the textfield is empty | |
open var hidesWhenEmpty: Bool? { | |
didSet { | |
DispatchQueue.main.async { | |
self.autoCompleteTableView?.isHidden = self.hidesWhenEmpty! | |
} | |
} | |
} | |
/// The autoCompleteTableView height | |
open var autoCompleteTableHeight:CGFloat?{ | |
didSet { | |
redrawTable() | |
} | |
} | |
/// this is the x margin for table view from textfield | |
open var autoCompleteTableMargin = CGFloat() | |
// MARK: - INIT FUNCTIONS | |
public required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
commonInit() | |
setupAutocompleteTable(superview!) | |
} | |
public override init(frame: CGRect) { | |
super.init(frame: frame) | |
commonInit() | |
translatesAutoresizingMaskIntoConstraints = false | |
// setupAutocompleteTable(superview!) | |
if let newSuperviews = superview { | |
setupAutocompleteTable(newSuperviews) | |
} | |
} | |
open override func awakeFromNib() { | |
super.awakeFromNib() | |
commonInit() | |
setupAutocompleteTable(superview!) | |
} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
commonInit() | |
setupAutocompleteTable(superview!) | |
} | |
// open override func willMove(toSuperview newSuperview: UIView?) { | |
// super.willMove(toSuperview: newSuperview) | |
// commonInit() | |
// setupAutocompleteTable(newSuperview!) | |
// } | |
public override func willMove(toSuperview newSuperview: UIView?) { | |
super.willMove(toSuperview: newSuperview) | |
commonInit() | |
if let newSuperviews = newSuperview { | |
setupAutocompleteTable(newSuperviews) | |
} | |
} | |
fileprivate func commonInit(){ | |
hidesWhenEmpty = true | |
highLightTypeTextedEnabled = false | |
highLightTypeTextedAttributes = [NSAttributedString.Key.font: | |
UIFont(name: "Helvetica-Bold", size: 12.0)!, | |
NSAttributedString.Key.foregroundColor: UIColor.white] | |
self.clearButtonMode = .always | |
self.addTarget(self, action: #selector(PlaceSearchField.textFieldDidChange), for: .editingChanged) | |
self.addTarget(self, action: #selector(PlaceSearchField.textFieldDidEndEditing), for: .editingDidEnd) | |
} | |
fileprivate func setupAutocompleteTable(_ view: UIView) { | |
autoCompleteTableMargin = 10.0 | |
// let tableView = UITableView(frame: CGRect(x: self.frame.origin.x + autoCompleteTableMargin/2, y: self.frame.origin.y + self.frame.height, width: (self.frame.width - autoCompleteTableMargin), height: 30.0)) | |
let tableView = UITableView(frame: .zero) | |
tableView.translatesAutoresizingMaskIntoConstraints = false | |
// tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true | |
// tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true | |
// tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true | |
// tableView.centerXAnchor.cons | |
// tableView.heightAnchor.constraint(equalToConstant: 30).isActive = true | |
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) | |
// tableView.backgroundColor = .red | |
view.addSubview(tableView) | |
autoCompleteTableView = tableView | |
autoCompleteTableHeight = 200.0 | |
} | |
fileprivate func redrawTable() { | |
if let autoCompleteTableView = autoCompleteTableView, let autoCompleteTableHeight = autoCompleteTableHeight { | |
var newFrame = autoCompleteTableView.frame | |
newFrame.size.height = autoCompleteTableHeight | |
autoCompleteTableView.frame = newFrame | |
} | |
} | |
// MARK: - Private Methods | |
fileprivate func showHighlightedTypedText(aStr: NSString) -> NSAttributedString { | |
// highLightTypeTextedAttributes = [NSAttributedString.Key.font.rawValue: | |
// UIFont(name: "Helvetica-Bold", size: 12.0)!, | |
// NSAttributedString.Key.foregroundColor: UIColor.white] as? [NSAttributedString.Key.RawValue: AnyObject] | |
let attrs = [NSAttributedString.Key.foregroundColor: autoCompleteTextColor, NSAttributedString.Key.font: autoCompleteTextFont] as [NSAttributedString.Key: Any] | |
let range = aStr.range(of: text!, options: .caseInsensitive) | |
let attString = NSMutableAttributedString(string: aStr as String, attributes: attrs) | |
attString.addAttributes(highLightTypeTextedAttributes!, range: range) | |
autoCompleteTextColor = UIColor.gray | |
return attString | |
} | |
// MARK: - AJAutoCompleteTextfieldDelegate | |
@objc func textFieldDidChange(){ | |
let placesClient = GMSPlacesClient() | |
placesClient.autocompleteQuery(text!, bounds: nil, filter: nil, callback: { (results, error) in | |
DispatchQueue.main.async { | |
self.autoCompletePlacesData.removeAll() | |
if results != nil { | |
for result in results!{ | |
self.autoCompletePlacesData.append(result.attributedFullText.string) | |
} | |
} | |
if self.autoCompletePlacesData.count != 0{ | |
self.hidesWhenEmpty = false | |
if self.autoCompletePlacesData.count < self.maxAutoCompleteDataCount{ | |
self.autoCompleteTableHeight = self.autoCompleteTableView?.contentSize.height | |
}else{ | |
self.autoCompleteTableHeight = 200 | |
} | |
self.autoCompleteTableView?.reloadData() | |
}else{ | |
self.hidesWhenEmpty = true | |
} | |
self.autoCompleteTableView?.isHidden = self.hidesWhenEmpty! | |
} | |
}) | |
} | |
@objc func textFieldDidEndEditing() { | |
autoCompleteTableView?.isHidden = true | |
} | |
} | |
// MARK: - UITableViewDataSource & UITableViewDelegate | |
extension PlaceSearchField: UITableViewDataSource, UITableViewDelegate { | |
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return autoCompletePlacesData.count | |
} | |
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cellIdentifier = "autocompleteCellIdentifier" | |
var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) | |
if cell == nil{ | |
cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier) | |
} | |
if highLightTypeTextedEnabled!{ | |
cell?.textLabel?.attributedText = showHighlightedTypedText(aStr: autoCompletePlacesData[indexPath.row] as NSString) | |
}else{ | |
cell?.textLabel?.font = autoCompleteTextFont | |
cell?.textLabel?.textColor = autoCompleteTextColor | |
cell?.textLabel?.text = autoCompletePlacesData[indexPath.row] | |
} | |
cell?.textLabel?.numberOfLines = 0 | |
cell?.contentView.gestureRecognizers = nil | |
return cell! | |
} | |
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
let cell = tableView.cellForRow(at: indexPath) | |
if let selectedText = cell?.textLabel?.text { | |
self.text = selectedText | |
self.resignFirstResponder() | |
selectedPlace!(selectedText, indexPath) | |
} | |
DispatchQueue.main.async(execute: { () -> Void in | |
tableView.isHidden = self.hidesWhenSelected | |
}) | |
} | |
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { | |
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)){ | |
cell.separatorInset = autoCompleteSeparatorInset | |
} | |
if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)){ | |
cell.preservesSuperviewLayoutMargins = false | |
} | |
if cell.responds(to: #selector(setter: UIView.layoutMargins)){ | |
cell.layoutMargins = autoCompleteSeparatorInset | |
} | |
} | |
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { | |
return autoCompleteCellHeight | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment