Toggle 在最大行数后启用 UITextView 滚动
Posted
技术标签:
【中文标题】Toggle 在最大行数后启用 UITextView 滚动【英文标题】:Toggle Enabling UITextView Scroll After Max Number of Lines 【发布时间】:2020-05-23 08:00:27 【问题描述】:我在 inputContainerView 中有一个 uitextview
subview
,因为它可能出现在消息传递应用程序中。
以编程方式,在加载时,uitextview
的高度锚点在 inputContainerView 初始化时设置。当键入更多的文本行时,此约束在增加容器高度方面非常有效。
我的目标是在达到 X 行后限制 uitextview
的高度,此后键入的任何行都可以滚动。同样,当行数低于最大值时,它会返回其原始形式 - 不可滚动并根据内容自动调整高度。
经过多次试验和研究,一旦达到最大行数,我已经设法获得固定的高度,但是一旦行数下降到以下,我似乎无法弄清楚如何将其恢复为原始形式最大。 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
【问题讨论】:
解决了你的问题吗? 【参考方案1】:你把一个简单的问题复杂化了,这里是你如何实现你想要的
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 框架小于实际内容大小,因此会自动滚动
希望对你有帮助
【讨论】:
【参考方案2】:也可以禁用初始 textView 的 isScrollEnabled
,然后像这样实现文本视图调整大小:
private var heightConstraint: NSLayoutConstraint?
private let inputLinesScrollThreshold = 5
func textViewDidChange(_ textView: UITextView)
let isConstraintActive = heightConstraint.flatMap $0.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()
【讨论】:
以上是关于Toggle 在最大行数后启用 UITextView 滚动的主要内容,如果未能解决你的问题,请参考以下文章