在许多文本输入字段(例如imessage中的字段)中,一旦文本到达字段的右边缘,字段就会增加其高度并相应地包装文本。这是我想要在我正在创建的搜索栏中实现的效果,但是我无法使调整大小正常工作。
这是我到目前为止所拥有的......
import UIKit
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UITextFieldDelegate {
var bottomConstraint: NSLayoutConstraint?
let searchBarView: UIView = {
let sbv = UIView()
sbv.backgroundColor = UIColor.lightGray
sbv.layer.cornerRadius = 5
return sbv
}()
let searchBar: UITextField = {
let sBar = UITextField()
sBar.textAlignment = .left
sBar.backgroundColor = UIColor.red
return sBar
}()
func setupKeyboardObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func handleKeyboardNotification(_ notification: Notification) {
if let userInfo = notification.userInfo {
let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
//print(keyboardFrame as Any)
let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow
let isKeybobardNotShowing = notification.name == NSNotification.Name.UIKeyboardWillHide
bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame!.height : 0
UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completed) in
})
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Search Bar"
collectionView?.backgroundColor = UIColor.white
self.searchBar.delegate = self
view.addSubview(searchBarView)
searchBarView.addSubview(searchBar)
setupKeyboardObservers()
//searchbarview constraints
searchBarView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: searchBarView, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 0.75, constant: 0).isActive = true
NSLayoutConstraint(item: searchBarView, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 0.04, constant: 0).isActive = true
NSLayoutConstraint(item: searchBarView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 0.85, constant: 0).isActive = true
//searchbar constraints
searchBarView.addConstraintsWithFormat("H:|-2-[v0]-2-|", views: searchBar)
searchBarView.addConstraintsWithFormat("V:|-2-[v0]-2-|", views: searchBar)
bottomConstraint = NSLayoutConstraint(item: searchBarView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
searchBar.endEditing(true)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentString: String = (textField.text! as NSString).replacingCharacters(in: range, with: string)
let length: Int = (currentString.characters.count )
let messageText = currentString
let size = CGSize(width: self.view.frame.width * 0.75, height: self.view.frame.height * 1.25)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 20)], context: nil)
if estimatedFrame.width >= self.view.frame.width * 0.745 {
searchBarView.frame.size.height = estimatedFrame.height
searchBar.frame.size.height = estimatedFrame.height - 2
UIView.animate(withDuration: 0.2, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completed) in
self.view.addConstraint(self.bottomConstraint!)
})
}else{
NSLayoutConstraint(item: searchBarView, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 0.75, constant: 0).isActive = true
NSLayoutConstraint(item: searchBarView, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 0.04, constant: 0).isActive = true
NSLayoutConstraint(item: searchBarView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 0.85, constant: 0).isActive = true
}
return true
}
}
extension UIView {
func addConstraintsWithFormat(_ format: String, views : UIView...) {
var viewsDictionary = [String: UIView]()
for(index, view) in views.enumerated(){
let key = "v\(index)"
viewsDictionary[key] = view
view.translatesAutoresizingMaskIntoConstraints = false
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
}
有什么建议吗?