【问题标题】:UITextView height to change dynamically when typing / without using storyboardsUITextView 高度在键入/不使用情节提要时动态更改
【发布时间】:2018-06-17 20:09:49
【问题描述】:

我有这个 UITextView 并且我希望它的高度在用户输入时动态改变。我想以编程方式进行。我在另一个 UIView 上方有 UITextView。约束设置如下:

 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 容器的高度。

【问题讨论】:

  • 您是否禁用了 addtextview 的滚动功能?
  • @DonMag 是的!滚动已禁用。
  • @OsamaNaeem - 好的,那么当你得到一个换行符时会发生什么?文本视图是否滚动?它是否会调整大小,但不会将“低/中/高/紧急”行向上推?
  • @DonMag 它根本不调整大小。不知道为什么?

标签: ios swift textview height programmatically


【解决方案1】:

objective-c 中有一个聪明的答案here,您可以在其中检测 textView 中的换行符,并适当调整 textView 的框架。这是快速版本:

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 变小了,但是让它变大是你的约束问题。

【讨论】:

  • 仍然无法工作。我必须调整我的约束吗?我被这个问题困了好几个星期了,现在还不知道怎么解决?
  • @OsamaNaeem 您必须更具体地说明什么不起作用。你是如何更新你的框架的高度的?您是否正确设置了约束?
  • 我正在使用的约束已发布在上面的主帖中。至于更改高度:我正在测量内容大小和高度并将其应用于 textview 高度。遵循此代码link
【解决方案2】:

首先确保您的类采用 UITextViewDelegate 协议,以便在文本发生如下变化时通知您:

class MyClass: UIViewContoller, UITextViewDelegate

接下来在你的类的某个地方定义这个变量,这样你就可以跟踪约束中的高度:

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 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()
    }
}

【讨论】:

  • 宾果游戏!它可以工作,但有几个问题: 1. 首先,我必须删除底部约束,然后文本视图开始动态改变高度。 2. textview 正在改变高度但正在向下移动。我希望它向上移动并保持底部间距。
  • addtasktextview 是否受到任何约束,这可能会阻止它改变高度,因为它们也会阻止 addtextview 改变高度。如果没有看到更多你的项目,很难说。
  • 不错的答案兄弟
  • @UpholderOfTruth,为我工作,很好的答案。
【解决方案3】:

在实现了“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()
}

希望这会有所帮助:)

【讨论】:

  • 阻止我的 textView 增长到一定高度,这是完美的解决方案,正是我正在寻找的。我使用了 200 和 view.layoutIfNeeded() :)
  • 你应该将你的答案添加到这个问题stackoverflow.com/q/38415847/4833705。您在这里的答案是一个非常简单的解决方案
猜你喜欢
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多