在最大行数后切换启用 UITextView 滚动
Toggle Enabling UITextView Scroll After Max Number of Lines
我在 inputContainerView 中有一个 uitextview
subview
,因为它可能出现在消息传递应用程序中。
以编程方式,在加载时,uitextview
的高度锚点是在初始化 inputContainerView 时设置的。随着键入更多文本行,此约束在增加容器高度方面效果很好。
我的目标是在达到 X 行之后限制 uitextview
的高度,在此之后键入的任何行都可以滚动。同样,当行数低于最大值时,它 return 恢复为原始形式 - 不可滚动并根据内容自动调整高度。
经过多次试验和研究,我已经设法让高度在达到最大行数后固定,但我似乎无法弄清楚一旦行数低于最大值。 uitextview
高度似乎停留在行数已达到最大值的高度。
相关代码如下:
//Container View Initialization, onLoad Frame Height is set to 60
override init(frame: CGRect) {
super.init(frame: frame)
autoresizingMask = .flexibleHeight
addSubview(chatTextView)
textView.heightAnchor.constraint(greaterThanOrEqualToConstant: frame.height - 20).isActive = true
}
//TextView Delegate
var isTextViewOverMaxHeight = false
var textViewMaxHeight: CGFloat = 0.0
func textViewDidChange(_ textView: UITextView) {
let numberOfLines = textView.contentSize.height/(textView.font?.lineHeight)!
if Int(numberOfLines) > 5 {
if !isTextViewOverMaxHeight {
containerView.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 40).isActive = false
containerView.textView.heightAnchor.constraint(equalToConstant:
containerView.textView.frame.height).isActive = true
containerView.textView.isScrollEnabled = true
textViewMaxHeight = containerView.textView.frame.height
isTextViewOverMaxHeight = true
}
} else {
if isTextViewOverMaxHeight {
containerView.textView.heightAnchor.constraint(equalToConstant: textViewMaxHeight).isActive = false
containerView.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 40).isActive = true
containerView.textView.isScrollEnabled = false
isTextViewOverMaxHeight = false
}
}
}
您将手头的一个简单问题复杂化了,这里是您如何实现您想要的
class ViewController: UIViewController {
var heightConstraint: NSLayoutConstraint!
var heightFor5Lines: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView(frame: CGRect.zero)
textView.delegate = self
textView.backgroundColor = UIColor.red
textView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(textView)
textView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
textView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
heightConstraint = textView.heightAnchor.constraint(equalToConstant: 30.0)
heightConstraint.isActive = true
}
}
extension ViewController: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
let numberOfLines = textView.contentSize.height/(textView.font?.lineHeight)!
if Int(numberOfLines) > 5 {
self.heightConstraint.constant = heightFor5Lines
} else {
if Int(numberOfLines) == 5 {
self.heightFor5Lines = textView.contentSize.height
}
self.heightConstraint.constant = textView.contentSize.height
}
textView.layoutIfNeeded()
}
}
这是如何工作的?:
很简单,您的 textView 以一定高度开始(这里需要高度限制,因为我既没有禁用它的滚动也没有提供底部限制,所以它没有足够的数据来评估其固有高度)每次更改文本时,您都会检查行数,只要行数小于阈值行数,您就会不断增加 textView 的高度约束,以便其框架与 contentSize 匹配(因此不会滚动),一旦它命中预期的行数,您限制高度,以便 textView 框架小于实际内容大小,因此自动滚动
希望对您有所帮助
也可以禁用初始 textView 的 isScrollEnabled
,然后像这样实现文本视图大小调整:
private var heightConstraint: NSLayoutConstraint?
private let inputLinesScrollThreshold = 5
func textViewDidChange(_ textView: UITextView) {
let isConstraintActive = heightConstraint.flatMap { [=10=].isActive } ?? false
let lineHeight = textView.font?.lineHeight ?? 1
let linesCount = Int(textView.contentSize.height / lineHeight)
if isConstraintActive == false {
heightConstraint = textView.heightAnchor.constraint(equalToConstant: textView.frame.height)
heightConstraint?.isActive = true
textView.isScrollEnabled = true
} else {
heightConstraint?.constant = linesCount > inputLinesScrollThreshold ?
lineHeight * CGFloat(inputLinesScrollThreshold) : textView.contentSize.height
}
textView.layoutIfNeeded()
}
我在 inputContainerView 中有一个 uitextview
subview
,因为它可能出现在消息传递应用程序中。
以编程方式,在加载时,uitextview
的高度锚点是在初始化 inputContainerView 时设置的。随着键入更多文本行,此约束在增加容器高度方面效果很好。
我的目标是在达到 X 行之后限制 uitextview
的高度,在此之后键入的任何行都可以滚动。同样,当行数低于最大值时,它 return 恢复为原始形式 - 不可滚动并根据内容自动调整高度。
经过多次试验和研究,我已经设法让高度在达到最大行数后固定,但我似乎无法弄清楚一旦行数低于最大值。 uitextview
高度似乎停留在行数已达到最大值的高度。
相关代码如下:
//Container View Initialization, onLoad Frame Height is set to 60
override init(frame: CGRect) {
super.init(frame: frame)
autoresizingMask = .flexibleHeight
addSubview(chatTextView)
textView.heightAnchor.constraint(greaterThanOrEqualToConstant: frame.height - 20).isActive = true
}
//TextView Delegate
var isTextViewOverMaxHeight = false
var textViewMaxHeight: CGFloat = 0.0
func textViewDidChange(_ textView: UITextView) {
let numberOfLines = textView.contentSize.height/(textView.font?.lineHeight)!
if Int(numberOfLines) > 5 {
if !isTextViewOverMaxHeight {
containerView.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 40).isActive = false
containerView.textView.heightAnchor.constraint(equalToConstant:
containerView.textView.frame.height).isActive = true
containerView.textView.isScrollEnabled = true
textViewMaxHeight = containerView.textView.frame.height
isTextViewOverMaxHeight = true
}
} else {
if isTextViewOverMaxHeight {
containerView.textView.heightAnchor.constraint(equalToConstant: textViewMaxHeight).isActive = false
containerView.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 40).isActive = true
containerView.textView.isScrollEnabled = false
isTextViewOverMaxHeight = false
}
}
}
您将手头的一个简单问题复杂化了,这里是您如何实现您想要的
class ViewController: UIViewController {
var heightConstraint: NSLayoutConstraint!
var heightFor5Lines: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView(frame: CGRect.zero)
textView.delegate = self
textView.backgroundColor = UIColor.red
textView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(textView)
textView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
textView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
heightConstraint = textView.heightAnchor.constraint(equalToConstant: 30.0)
heightConstraint.isActive = true
}
}
extension ViewController: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
let numberOfLines = textView.contentSize.height/(textView.font?.lineHeight)!
if Int(numberOfLines) > 5 {
self.heightConstraint.constant = heightFor5Lines
} else {
if Int(numberOfLines) == 5 {
self.heightFor5Lines = textView.contentSize.height
}
self.heightConstraint.constant = textView.contentSize.height
}
textView.layoutIfNeeded()
}
}
这是如何工作的?:
很简单,您的 textView 以一定高度开始(这里需要高度限制,因为我既没有禁用它的滚动也没有提供底部限制,所以它没有足够的数据来评估其固有高度)每次更改文本时,您都会检查行数,只要行数小于阈值行数,您就会不断增加 textView 的高度约束,以便其框架与 contentSize 匹配(因此不会滚动),一旦它命中预期的行数,您限制高度,以便 textView 框架小于实际内容大小,因此自动滚动
希望对您有所帮助
也可以禁用初始 textView 的 isScrollEnabled
,然后像这样实现文本视图大小调整:
private var heightConstraint: NSLayoutConstraint?
private let inputLinesScrollThreshold = 5
func textViewDidChange(_ textView: UITextView) {
let isConstraintActive = heightConstraint.flatMap { [=10=].isActive } ?? false
let lineHeight = textView.font?.lineHeight ?? 1
let linesCount = Int(textView.contentSize.height / lineHeight)
if isConstraintActive == false {
heightConstraint = textView.heightAnchor.constraint(equalToConstant: textView.frame.height)
heightConstraint?.isActive = true
textView.isScrollEnabled = true
} else {
heightConstraint?.constant = linesCount > inputLinesScrollThreshold ?
lineHeight * CGFloat(inputLinesScrollThreshold) : textView.contentSize.height
}
textView.layoutIfNeeded()
}