UITextView 高度在键入时动态变化/不使用情节提要
UITextView height to change dynamically when typing / without using storyboards
我有这个 UITextView 并且我希望它的高度在用户输入时动态改变。我想以编程方式进行。我的 UITextView 位于另一个 UIView 之上。约束设置如下:
addtextview.leadingAnchor.constraint(equalTo: addtasktextview.leadingAnchor, constant: 8).isActive = true
addtextview.trailingAnchor.constraint(equalTo: addtasktextview.trailingAnchor, constant: -8).isActive = true
addtextview.topAnchor.constraint(equalTo: addtasktextview.topAnchor, constant: 8).isActive = true
addtextview.bottomAnchor.constraint(equalTo: addtasktextview.bottomAnchor, constant: -40).isActive = true
有趣的是,我也在 tableViewCells 中使用 textview,并通过仅使用此约束方法动态更改高度,但在这里它不起作用。
我希望 textview 的高度以向上移动的方式增加。因此,当新行开始时,顶部应移动以保持下方的间距。
我该怎么做?帮助将不胜感激。
更新:我能够使用下面@upholder-of-truth 的回答让它工作。我还能够通过找到 textview 正常高度和 newSize.height 之间的差异然后将该差异添加到容器的高度来动态更改父 UIView 容器高度。
在 objective-c 中有一个聪明的答案 here,您可以在其中检测 textView 中的换行符,并适当地调整 textView 的框架。这是 swift 版本:
var previousPosition:CGRect = CGRect.zero
func textViewDidChange(_ textView: UITextView) {
let position:UITextPosition = textView.endOfDocument
let currentPosition:CGRect = textView.caretRect(for: position)
if(currentPosition.origin.y > previousPosition.origin.y){
/*Update your textView's height here*/
previousPosition = currentPosition
}
}
确保 textView 的视图控制器采用 UITextViewDelegate
并设置 self.textView.delegate = self
Demo 这里的textView变小了,但是让它变大是你的约束问题。
首先确保您的 class 采用 UITextViewDelegate 协议,这样当文本发生如下变化时您可以得到通知:
class MyClass: UIViewContoller, UITextViewDelegate
接下来在您的 class 中的某处定义此变量,以便您可以跟踪约束中的高度:
var textHeightConstraint: NSLayoutConstraint!
接下来添加以下约束并激活它:
self.textHeightConstraint = addtextview.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true
(如果您不在 viewDidLoad 中执行此操作,则需要将 textHeightConstraint 设为可选)
接下来订阅委托(如果尚未完成):
addTextView.delegate = self
添加重新计算高度约束的函数:
func adjustTextViewHeight() {
let fixedWidth = addtextview.frame.size.width
let newSize = addtextview.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}
接下来在创建约束以设置初始大小后添加对该函数的调用:
self.adjustTextViewHeight()
最后添加这个方法来在文本变化时调整高度:
func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}
以防万一这一切都令人困惑,这是 UIViewController 的子 class 中的一个最小示例:
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet var textView: UITextView!
@IBOutlet var textHolder: UIView!
var textHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
textView.leadingAnchor.constraint(equalTo: textHolder.leadingAnchor, constant: 8).isActive = true
textView.trailingAnchor.constraint(equalTo: textHolder.trailingAnchor, constant: -8).isActive = true
textView.topAnchor.constraint(equalTo: textHolder.topAnchor, constant: 8).isActive = true
textView.bottomAnchor.constraint(equalTo: textHolder.bottomAnchor, constant: -40).isActive = true
self.textHeightConstraint = textView.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true
self.adjustTextViewHeight()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}
func adjustTextViewHeight() {
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}
}
在实施了"Upholder Of Truth"中所选答案的解决方案后,我想知道如何摆脱因更改高度约束而带来的奇怪的文本底部偏移。
一个简单的解决方案是在初始化开始时设置它:
textView.isScrollEnabled = false
最后,如果您需要您的 textview 在特定高度后停止增长,您可以将 "adjustTextViewHeight" 函数更改为:
func adjustTextViewHeight() {
let fixedWidth = growingTextView.frame.size.width
let newSize = growingTextView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
if newSize.height > 100 {
growingTextView.isScrollEnabled = true
}
else {
growingTextView.isScrollEnabled = false
textViewHeightConstraint.constant = newSize.height
}
view.layoutSubviews()
}
希望这对您有所帮助:)
我有这个 UITextView 并且我希望它的高度在用户输入时动态改变。我想以编程方式进行。我的 UITextView 位于另一个 UIView 之上。约束设置如下:
addtextview.leadingAnchor.constraint(equalTo: addtasktextview.leadingAnchor, constant: 8).isActive = true
addtextview.trailingAnchor.constraint(equalTo: addtasktextview.trailingAnchor, constant: -8).isActive = true
addtextview.topAnchor.constraint(equalTo: addtasktextview.topAnchor, constant: 8).isActive = true
addtextview.bottomAnchor.constraint(equalTo: addtasktextview.bottomAnchor, constant: -40).isActive = true
有趣的是,我也在 tableViewCells 中使用 textview,并通过仅使用此约束方法动态更改高度,但在这里它不起作用。 我希望 textview 的高度以向上移动的方式增加。因此,当新行开始时,顶部应移动以保持下方的间距。
我该怎么做?帮助将不胜感激。
更新:我能够使用下面@upholder-of-truth 的回答让它工作。我还能够通过找到 textview 正常高度和 newSize.height 之间的差异然后将该差异添加到容器的高度来动态更改父 UIView 容器高度。
在 objective-c 中有一个聪明的答案 here,您可以在其中检测 textView 中的换行符,并适当地调整 textView 的框架。这是 swift 版本:
var previousPosition:CGRect = CGRect.zero
func textViewDidChange(_ textView: UITextView) {
let position:UITextPosition = textView.endOfDocument
let currentPosition:CGRect = textView.caretRect(for: position)
if(currentPosition.origin.y > previousPosition.origin.y){
/*Update your textView's height here*/
previousPosition = currentPosition
}
}
确保 textView 的视图控制器采用 UITextViewDelegate
并设置 self.textView.delegate = self
Demo 这里的textView变小了,但是让它变大是你的约束问题。
首先确保您的 class 采用 UITextViewDelegate 协议,这样当文本发生如下变化时您可以得到通知:
class MyClass: UIViewContoller, UITextViewDelegate
接下来在您的 class 中的某处定义此变量,以便您可以跟踪约束中的高度:
var textHeightConstraint: NSLayoutConstraint!
接下来添加以下约束并激活它:
self.textHeightConstraint = addtextview.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true
(如果您不在 viewDidLoad 中执行此操作,则需要将 textHeightConstraint 设为可选)
接下来订阅委托(如果尚未完成):
addTextView.delegate = self
添加重新计算高度约束的函数:
func adjustTextViewHeight() {
let fixedWidth = addtextview.frame.size.width
let newSize = addtextview.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}
接下来在创建约束以设置初始大小后添加对该函数的调用:
self.adjustTextViewHeight()
最后添加这个方法来在文本变化时调整高度:
func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}
以防万一这一切都令人困惑,这是 UIViewController 的子 class 中的一个最小示例:
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet var textView: UITextView!
@IBOutlet var textHolder: UIView!
var textHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
textView.leadingAnchor.constraint(equalTo: textHolder.leadingAnchor, constant: 8).isActive = true
textView.trailingAnchor.constraint(equalTo: textHolder.trailingAnchor, constant: -8).isActive = true
textView.topAnchor.constraint(equalTo: textHolder.topAnchor, constant: 8).isActive = true
textView.bottomAnchor.constraint(equalTo: textHolder.bottomAnchor, constant: -40).isActive = true
self.textHeightConstraint = textView.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true
self.adjustTextViewHeight()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}
func adjustTextViewHeight() {
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}
}
在实施了"Upholder Of Truth"中所选答案的解决方案后,我想知道如何摆脱因更改高度约束而带来的奇怪的文本底部偏移。
一个简单的解决方案是在初始化开始时设置它:
textView.isScrollEnabled = false
最后,如果您需要您的 textview 在特定高度后停止增长,您可以将 "adjustTextViewHeight" 函数更改为:
func adjustTextViewHeight() {
let fixedWidth = growingTextView.frame.size.width
let newSize = growingTextView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
if newSize.height > 100 {
growingTextView.isScrollEnabled = true
}
else {
growingTextView.isScrollEnabled = false
textViewHeightConstraint.constant = newSize.height
}
view.layoutSubviews()
}
希望这对您有所帮助:)