【发布时间】:2018-11-08 11:05:22
【问题描述】:
我想要的只是在您输入/粘贴时调整UITextView 的大小。它应该是可滚动的,因为我不希望 UITextView 填满屏幕。用这几行代码就可以轻松实现。
@IBOutlet weak var mainTextView: UITextView!
@IBOutlet weak var mainTextViewHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.mainTextView.delegate = self
}
// This method is used for calculating the string's height in a UITextField
func heightOf(text: String, for textView: UITextView) -> CGFloat {
let nsstring: NSString = text as NSString
let boundingSize = nsstring.boundingRect(
with: CGSize(width: textView.frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: textView.font!],
context: nil).size
return ceil(boundingSize.height + textView.textContainerInset.top + textView.textContainerInset.bottom)
}
// This method calculates the UITextView's new height
func calculateHeightFor(text: String, in textView: UITextView) -> CGFloat {
let newString: String = textView.text ?? ""
let minHeight = self.heightOf(text: "", for: textView) // 1 line height
let maxHeight = self.heightOf(text: "\n\n\n\n\n", for: textView) // 6 lines height
let contentHeight = self.heightOf(text: newString, for: textView) // height of the new string
return min(max(minHeight, contentHeight), maxHeight)
}
// The lines inside will change the UITextView's height
func textViewDidChange(_ textView: UITextView) {
self.mainTextViewHeightConstraint.constant = calculateHeightFor(
text: textView.text ?? "",
in: textView)
}
这非常有效,除非您粘贴多行文本,或按 enter(换行符)。
为了解决粘贴问题,各种 SO 问题建议我要么创建 UITextView 的子类来覆盖 paste(_:) 方法,要么使用 textView(_: shouldChangeTextIn....) 委托方法。经过几次实验,最好的答案是使用shouldChangeTextIn 方法,这导致我的代码变成了这个
// I replaced `textViewDidChange(_ textView: UITextView)` with this
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
self.mainTextViewHeightConstraint.constant = calculateHeightFor(
text: ((textView.text ?? "") as NSString).replacingCharacters(in: range, with: text),
in: textView)
return true
}
现在应该发生的是,当您粘贴文本时,UITextView 应该如下所示。 (粘贴的字符串是“A\nA\nA\nA\nA”或 5 行只是 A)
可是变成了这个样子
从截图中可以看出,textContainer 的框架在错误的位置。现在奇怪的是,它似乎只在您粘贴到空的UITextView 时才会发生。
我尝试过设置和重置UITextView 的frame.size,我尝试过手动设置NSTextContainer 的大小以及其他一些棘手的解决方案,但我似乎无法修复它。我该如何解决这个问题?
附加信息:
查看视图调试器后,输入 enter(换行符)时的外观如下所示
如我们所见,文本容器的位置错误。
毕竟,添加UIView.animate 块似乎可以解决一些问题,但不是全部。为什么会这样?
// These snippet kind of fixes the problem
self.mainTextViewHeightConstraint.constant = calculateHeightFor(
text: textView.text ?? "",
in: textView)
UIView.animate(withDuration: 0.1) {
self.view.layoutIfNeeded()
}
注意:我没有放置UIView.animate 解决方案,因为它没有涵盖所有的错误。
注意:
操作系统支持:iOS 8.xx - iOS 12.xx Xcode:v10.10 Swift:3 和 4(我都试过了)
PS:是的,我已经处理过其他一些 SO 问题,例如底部列出的问题和其他一些问题
【问题讨论】:
标签: ios swift uitextview