From 466d1a8aa56791ec81a34e18ff3fb58eefba708b Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 7 Jun 2017 21:47:50 -0700 Subject: [PATCH 1/3] Resizable text New feature: resizable text after selection in case of long text which is resized until fits. --- SearchTextField/Classes/SearchTextField.swift | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/SearchTextField/Classes/SearchTextField.swift b/SearchTextField/Classes/SearchTextField.swift index 3c461e9..bede482 100644 --- a/SearchTextField/Classes/SearchTextField.swift +++ b/SearchTextField/Classes/SearchTextField.swift @@ -68,6 +68,9 @@ open class SearchTextField: UITextField { /// Set your custom set of attributes in order to highlight the string found in each item open var highlightAttributes: [String: AnyObject] = [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 10)] + /// Automatically resize the text + open var resizableText: Bool = false + /// Start showing the default loading indicator, useful for searches that take some time. open func showLoadingIndicator() { self.rightViewMode = .always @@ -462,6 +465,22 @@ open class SearchTextField: UITextField { redrawSearchTableView() } } + + //Resizes the text until fits + internal func resizeText() { + if let text = self.text{ + let textString = text as NSString + var widthOfText = textString.size(attributes: [NSFontAttributeName : self.font!]).width + var widthOfFrame = self.frame.size.width + // decrease font size until it fits + while widthOfFrame - 5 < widthOfText { + let fontSize = self.font!.pointSize + self.font = self.font?.withSize(fontSize - 0.5) + widthOfText = textString.size(attributes: [NSFontAttributeName : self.font!]).width + widthOfFrame = self.frame.size.width + } + } + } } extension SearchTextField: UITableViewDelegate, UITableViewDataSource { @@ -510,6 +529,11 @@ extension SearchTextField: UITableViewDelegate, UITableViewDataSource { public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if itemSelectionHandler == nil { self.text = filteredResults[(indexPath as NSIndexPath).row].title + + if resizableText{ + self.resizeText() + } + } else { let index = indexPath.row itemSelectionHandler!(filteredResults, index) From e650a666ae4a16bbf17b55bfa59222df96a1731a Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 7 Jun 2017 22:51:04 -0700 Subject: [PATCH 2/3] Fixed resize on delete Fixed resizing when user deletes text --- SearchTextField/Classes/SearchTextField.swift | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/SearchTextField/Classes/SearchTextField.swift b/SearchTextField/Classes/SearchTextField.swift index bede482..a40ba52 100644 --- a/SearchTextField/Classes/SearchTextField.swift +++ b/SearchTextField/Classes/SearchTextField.swift @@ -5,17 +5,16 @@ // Created by Alejandro Pasccon on 4/20/16. // Copyright © 2016 Alejandro Pasccon. All rights reserved. // - import UIKit open class SearchTextField: UITextField { - + //////////////////////////////////////////////////////////////////////// // Public interface /// Maximum number of results to be shown in the suggestions list open var maxNumberOfResults = 0 - + /// Maximum height of the results list open var maxResultsListHeight = 0 @@ -24,7 +23,7 @@ open class SearchTextField: UITextField { /// Indicate if keyboard is showing or not open var keyboardIsShowing = false - + /// Set your custom visual theme, or just choose between pre-defined SearchTextFieldTheme.lightTheme() and SearchTextFieldTheme.darkTheme() themes open var theme = SearchTextFieldTheme.lightTheme() { didSet { @@ -47,7 +46,7 @@ open class SearchTextField: UITextField { open func filterItems(_ items: [SearchTextFieldItem]) { filterDataSource = items } - + /// Set an array of strings to be used for suggestions open func filterStrings(_ strings: [String]) { var items = [SearchTextFieldItem]() @@ -67,22 +66,23 @@ open class SearchTextField: UITextField { /// Set your custom set of attributes in order to highlight the string found in each item open var highlightAttributes: [String: AnyObject] = [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 10)] - + /// Automatically resize the text open var resizableText: Bool = false + var originalFontSize: CGFloat = 0 /// Start showing the default loading indicator, useful for searches that take some time. open func showLoadingIndicator() { self.rightViewMode = .always indicator.startAnimating() } - + /// Hide the default loading indicator open func stopLoadingIndicator() { self.rightViewMode = .never indicator.stopAnimating() } - + /// When InlineMode is true, the suggestions appear in the same line than the entered string. It's useful for email domains suggestion for example. open var inlineMode: Bool = false { didSet { @@ -101,7 +101,7 @@ open class SearchTextField: UITextField { open var startSuggestingInmediately = false open var comparisonOptions: NSString.CompareOptions = [.caseInsensitive] - + //////////////////////////////////////////////////////////////////////// // Private implementation @@ -128,7 +128,7 @@ open class SearchTextField: UITextField { deinit { NotificationCenter.default.removeObserver(self) } - + override open func willMove(toSuperview newSuperview: UIView?) { super.willMove(toSuperview: newSuperview) @@ -137,6 +137,7 @@ open class SearchTextField: UITextField { self.addTarget(self, action: #selector(SearchTextField.textFieldDidEndEditing), for: .editingDidEnd) self.addTarget(self, action: #selector(SearchTextField.textFieldDidEndEditingOnExit), for: .editingDidEndOnExit) + NotificationCenter.default.addObserver(self, selector: #selector(SearchTextField.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SearchTextField.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SearchTextField.keyboardDidChangeFrame(_:)), name: NSNotification.Name.UIKeyboardDidChangeFrame, object: nil) @@ -154,6 +155,7 @@ open class SearchTextField: UITextField { // Create the loading indicator indicator.hidesWhenStopped = true self.rightView = indicator + } override open func rightViewRect(forBounds bounds: CGRect) -> CGRect { @@ -189,14 +191,14 @@ open class SearchTextField: UITextField { var newRect = self.placeholderRect(forBounds: self.bounds) var caretRect = self.caretRect(for: self.beginningOfDocument) let textRect = self.textRect(forBounds: self.bounds) - + if let range = textRange(from: beginningOfDocument, to: endOfDocument) { caretRect = self.firstRect(for: range) } newRect.origin.x = caretRect.origin.x + caretRect.size.width + textRect.origin.x newRect.size.width = newRect.size.width - newRect.origin.x - + if let placeholderLabel = placeholderLabel { placeholderLabel.font = self.font placeholderLabel.frame = newRect @@ -205,13 +207,13 @@ open class SearchTextField: UITextField { placeholderLabel?.font = self.font placeholderLabel?.backgroundColor = UIColor.clear placeholderLabel?.lineBreakMode = .byClipping - + if let placeholderColor = self.attributedPlaceholder?.attribute(NSForegroundColorAttributeName, at: 0, effectiveRange: nil) as? UIColor { placeholderLabel?.textColor = placeholderColor } else { placeholderLabel?.textColor = UIColor ( red: 0.8, green: 0.8, blue: 0.8, alpha: 1.0 ) } - + self.addSubview(placeholderLabel!) } } @@ -266,7 +268,7 @@ open class SearchTextField: UITextField { if self.isFirstResponder { superview?.bringSubview(toFront: self) } - + tableView.layer.borderColor = theme.borderColor.cgColor tableView.layer.cornerRadius = 2 tableView.separatorColor = theme.separatorColor @@ -323,17 +325,26 @@ open class SearchTextField: UITextField { } else { filter(false) prepareDrawTableResult() + + if resizableText{ + self.resizeText() + } } buildPlaceholderLabel() } + open func textFieldDidBeginEditing() { if startVisible && text!.isEmpty { clearResults() filter(true) } placeholderLabel?.attributedText = nil + + if let font = self.font{ + self.originalFontSize = font.pointSize + } } open func textFieldDidEndEditing() { @@ -341,7 +352,7 @@ open class SearchTextField: UITextField { tableView?.reloadData() placeholderLabel?.attributedText = nil } - + open func textFieldDidEndEditingOnExit() { if let firstElement = filteredResults.first { if let itemSelectionHandler = self.itemSelectionHandler { @@ -358,7 +369,8 @@ open class SearchTextField: UITextField { } } } - + + fileprivate func filter(_ addAll: Bool) { clearResults() @@ -402,7 +414,7 @@ open class SearchTextField: UITextField { } } } - + tableView?.reloadData() if inlineMode { @@ -469,6 +481,7 @@ open class SearchTextField: UITextField { //Resizes the text until fits internal func resizeText() { if let text = self.text{ + self.font = UIFont.systemFont(ofSize: originalFontSize) let textString = text as NSString var widthOfText = textString.size(attributes: [NSFontAttributeName : self.font!]).width var widthOfFrame = self.frame.size.width @@ -514,7 +527,7 @@ extension SearchTextField: UITableViewDelegate, UITableViewDataSource { cell!.detailTextLabel?.text = filteredResults[(indexPath as NSIndexPath).row].subtitle cell!.textLabel?.attributedText = filteredResults[(indexPath as NSIndexPath).row].attributedTitle cell!.detailTextLabel?.attributedText = filteredResults[(indexPath as NSIndexPath).row].attributedSubtitle - + cell!.imageView?.image = filteredResults[(indexPath as NSIndexPath).row].image cell!.selectionStyle = .none @@ -545,7 +558,6 @@ extension SearchTextField: UITableViewDelegate, UITableViewDataSource { //////////////////////////////////////////////////////////////////////// // Search Text Field Theme - public struct SearchTextFieldTheme { public var cellHeight: CGFloat public var bgColor: UIColor @@ -575,12 +587,11 @@ public struct SearchTextFieldTheme { //////////////////////////////////////////////////////////////////////// // Filter Item - public struct SearchTextFieldItem { // Private vars fileprivate var attributedTitle: NSMutableAttributedString? fileprivate var attributedSubtitle: NSMutableAttributedString? - + // Public interface public var title: String public var subtitle: String? @@ -591,12 +602,12 @@ public struct SearchTextFieldItem { self.subtitle = subtitle self.image = image } - + public init(title: String, subtitle: String?) { self.title = title self.subtitle = subtitle } - + public init(title: String) { self.title = title } @@ -606,7 +617,6 @@ public typealias SearchTextFieldItemHandler = (_ filteredResults: [SearchTextFie //////////////////////////////////////////////////////////////////////// // Suggestions List Direction - enum Direction { case down case up From c81d3a78b760ea548a8f8bb88a5288ec36e06b57 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 13 Jun 2017 13:04:13 -0700 Subject: [PATCH 3/3] Create README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a3fec7f..1354a01 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ You can decide wether to show the list as soon as the field is focused or when t You can also detects when the user stops typing, very useful when you can get a suggestion list from a remote server. **New Feature!** -Now you can make suggestions "inline", showing the first matched result as the placeholder (instead of the results list) and selecting it when the user touches the enter key. +Now you can: +- make suggestions "inline", showing the first matched result as the placeholder (instead of the results list) and selecting it when the user touches the enter key: +- activate the automatic text resize via _resizableText_ boolean. ------ ![alt_tag](https://raw.githubusercontent.com/apasccon/SearchTextField/master/Example/SearchTextField/SearchTextField_Demo.gif)