我正在使用一个名为growtextview的可可pod库,我在实现它时遇到了麻烦。某些限制似乎存在问题,但我无法识别它们。如果有人之前使用过这个库并且可以帮助实现它,那将非常感激。如果您知道任何类似的库或方法,请告诉我。
增长文本视图 https://github.com/KennethTsang/GrowingTextView
图书馆代码
import Foundation
import UIKit
@objc public protocol GrowingTextViewDelegate: UITextViewDelegate {
@objc optional func textViewDidChangeHeight(_ textView: GrowingTextView, height: CGFloat)
}
@IBDesignable @objc
open class GrowingTextView: UITextView {
// Maximum length of text. 0 means no limit.
@IBInspectable open var maxLength: Int = 0
// Trim white space and newline characters when end editing. Default is true
@IBInspectable open var trimWhiteSpaceWhenEndEditing: Bool = true
// Maximm height of the textview
@IBInspectable open var maxHeight: CGFloat = CGFloat(0)
// Placeholder properties
// Need to set both placeHolder and placeHolderColor in order to show placeHolder in the textview
@IBInspectable open var placeHolder: NSString? {
didSet { setNeedsDisplay() }
}
@IBInspectable open var placeHolderColor: UIColor = UIColor(white: 0.8, alpha: 1.0) {
didSet { setNeedsDisplay() }
}
@IBInspectable open var placeHolderLeftMargin: CGFloat = 5 {
didSet { setNeedsDisplay() }
}
override open var text: String! {
didSet {
setNeedsDisplay()
}
}
fileprivate weak var heightConstraint: NSLayoutConstraint?
// Initialize
override public init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
open override var intrinsicContentSize: CGSize {
return CGSize(width: UIViewNoIntrinsicMetric, height: 30)
}
func associateConstraints() {
// iterate through all text view's constraints and identify
// height,from: https://github.com/legranddamien/MBAutoGrowingTextView
for constraint in self.constraints {
if (constraint.firstAttribute == .height) {
if (constraint.relation == .equal) {
self.heightConstraint = constraint;
}
}
}
}
// Listen to UITextView notification to handle trimming, placeholder and maximum length
fileprivate func commonInit() {
self.contentMode = .redraw
associateConstraints()
NotificationCenter.default.addObserver(self, selector: #selector(textDidChange), name: NSNotification.Name.UITextViewTextDidChange, object: self)
NotificationCenter.default.addObserver(self, selector: #selector(textDidEndEditing), name: NSNotification.Name.UITextViewTextDidEndEditing, object: self)
}
// Remove notification observer when deinit
deinit {
NotificationCenter.default.removeObserver(self)
}
// Calculate height of textview
private var oldText = ""
private var oldWidth = CGFloat(0)
override open func layoutSubviews() {
super.layoutSubviews()
if text == oldText && oldWidth == bounds.width { return }
oldText = text
oldWidth = bounds.width
let size = sizeThatFits(CGSize(width:bounds.size.width, height: CGFloat.greatestFiniteMagnitude))
let height = maxHeight > 0 ? min(size.height, maxHeight) : size.height
if (heightConstraint == nil) {
heightConstraint = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: height)
addConstraint(heightConstraint!)
}
if height != heightConstraint?.constant {
self.heightConstraint!.constant = height;
scrollRangeToVisible(NSMakeRange(0, 0))
if let delegate = delegate as? GrowingTextViewDelegate {
delegate.textViewDidChangeHeight?(self, height: height)
}
}
}
// Show placeholder
override open func draw(_ rect: CGRect) {
super.draw(rect)
if text.isEmpty {
guard let placeHolder = placeHolder else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = textAlignment
let rect = CGRect(x: textContainerInset.left + placeHolderLeftMargin,
y: textContainerInset.top,
width: frame.size.width - textContainerInset.left - textContainerInset.right,
height: frame.size.height)
var attributes: [String: Any] = [
NSForegroundColorAttributeName: placeHolderColor,
NSParagraphStyleAttributeName: paragraphStyle
]
if let font = font {
attributes[NSFontAttributeName] = font
}
placeHolder.draw(in: rect, withAttributes: attributes)
}
}
// Trim white space and new line characters when end editing.
func textDidEndEditing(notification: Notification) {
if let notificationObject = notification.object as? GrowingTextView {
if notificationObject === self {
if trimWhiteSpaceWhenEndEditing {
text = text?.trimmingCharacters(in: .whitespacesAndNewlines)
setNeedsDisplay()
}
}
}
}
// Limit the length of text
func textDidChange(notification: Notification) {
if let notificationObject = notification.object as? GrowingTextView {
if notificationObject === self {
if maxLength > 0 && text.characters.count > maxLength {
let endIndex = text.index(text.startIndex, offsetBy: maxLength)
text = text.substring(to: endIndex)
undoManager?.removeAllActions()
}
setNeedsDisplay()
}
}
}
}
以下是我的实施
import UIKit
import GrowingTextView
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UITextViewDelegate, GrowingTextViewDelegate {
func textViewDidChangeHeight(_ textView: GrowingTextView, height: CGFloat) {
UIView.animate(withDuration: 0.2) {
self.view.layoutIfNeeded()
}
}
var bottomConstraint: NSLayoutConstraint?
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
})
}
}
deinit {
NotificationCenter.default.removeObserver(self)
}
let containerView: UIView = {
let cView = UIView()
cView.backgroundColor = UIColor.lightGray
return cView
}()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Search Bar"
collectionView?.backgroundColor = UIColor.white
setupKeyboardObservers()
automaticallyAdjustsScrollViewInsets = false
let textView = GrowingTextView()
textView.delegate = self
view.addSubview(containerView)
containerView.addSubview(textView)
containerView.translatesAutoresizingMaskIntoConstraints = false
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: containerView, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: containerView, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 0.1, constant: 0).isActive = true
NSLayoutConstraint(item: containerView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
bottomConstraint = NSLayoutConstraint(item: containerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
containerView.addConstraintsWithFormat("H:|-10-[v0]-10-|", views: textView)
containerView.addConstraintsWithFormat("V:|-10-[v0]-10-|", views: textView)
self.view.layoutIfNeeded()
textView.maxLength = 0
textView.trimWhiteSpaceWhenEndEditing = false
textView.placeHolder = "Say something..."
textView.font = UIFont.systemFont(ofSize: 22)
textView.placeHolderColor = UIColor(white: 0.8, alpha: 1.0)
textView.maxHeight = 70.0
textView.backgroundColor = UIColor.red
textView.layer.cornerRadius = 4.0
// //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.
textView.endEditing(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))
}
}
有什么建议吗?
编辑: 输出
2017-05-29 01:55:26.544 searchBar_v4 [53924:5226357]模拟器用户要求新的图形质量:10 2017-05-29 01:55:26.656157-0400 searchBar_v4 [53924:5226357] [LayoutConstraints]无法同时满足约束条件。 可能至少下列列表中的一个约束是您不想要的约束。 试试这个: (1)查看每个约束并试图找出你不期望的; (2)找到添加了不需要的约束或约束的代码并修复它。 ( “” “” “” “” “” )