• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 更改高度时,UITextView 的 textContainer 在错误的帧处呈现

[复制链接]
菜鸟教程小白 发表于 2022-12-11 20:47:28 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我想要的只是在您键入/粘贴时调整 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....) 委托(delegate)方法。经过几次实验,最好的答案是使用 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)

enter image description here

可是变成了这个样子

enter image description here

从截图中可以看出,textContainer 的框架在错误的位置。现在奇怪的是,它似乎只在你粘贴到一个空的 UITextView 时才会发生。

我尝试过设置和重置 UITextView 的 frame.size,我尝试过手动设置 NSTextContainer 的大小以及其他一些 hacky 解决方案,但是我似乎无法修复它。我该如何解决这个问题?

附加信息:

查看 View 调试器后,输入 enter(换行符)时的外观如下所示

enter image description here enter image description here

如我们所见,文本容器的位置错误。


毕竟添加 UIView.animate block 似乎解决了一些问题,但不是全部。为什么会这样?

// 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 问题,例如底部列出的问题和其他一些问题



Best Answer-推荐答案


可以忽略所有计算高度的代码,使用设置textview属性scrolling Enabled = false textview 将自行调整以适应文本内容 image1

然后根据需要更改代码

@IBOutlet weak var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.textView.text = "A\nA\nA\nA\nA"
}

结果会是这样 image2

关于ios - 更改高度时,UITextView 的 textContainer 在错误的帧处呈现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53206469/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap