UITextView - 根据 SwiftUI 中的内容调整大小

2023-11-21

我试图弄清楚如何使 UITextView 的大小取决于它在 SwiftUI 中的内容。我将 UITextView 包裹在UIViewRepresentable如下:

struct TextView: UIViewRepresentable {

    @Binding var showActionSheet: Bool

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextView {

        let uiTextView = UITextView()
        uiTextView.delegate = context.coordinator

        uiTextView.font = UIFont(name: "HelveticaNeue", size: 15)
        uiTextView.isScrollEnabled = true
        uiTextView.isEditable = true
        uiTextView.isUserInteractionEnabled = true
        uiTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)
        uiTextView.isEditable = false

        return uiTextView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = prepareText(question: question)

        var frame = uiView.frame
        frame.size.height = uiView.contentSize.height
        uiView.frame = frame
    }

    func prepareText(text: string) -> NSMutableAttributedString {
        ...................
        return attributedText
    }

    class Coordinator : NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ view: TextView) {
            self.parent = view
        }

        func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
            parent.showActionSheet = true
            return false
        }
    }
}

此外,我尝试根据 updateUIView 的内容大小更改框架大小,但没有任何效果。我想在这个阶段,视图甚至不是布局,它的框架正在其他地方被覆盖。如果有人能指出我正确的方向,我将非常感激。


我可以通过在 TextView 中绑定一个变量来实现这一点,封装视图使用该变量来设置框架高度。这是最小的 TextView 实现:

struct TextView: UIViewRepresentable {

    @Binding var text: String?
    @Binding var attributedText: NSAttributedString?
    @Binding var desiredHeight: CGFloat

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UITextView {

        let uiTextView = UITextView()
        uiTextView.delegate = context.coordinator

        // Configure text view as desired...
        uiTextView.font = UIFont(name: "HelveticaNeue", size: 15)

        return uiTextView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        if self.attributedText != nil {
            uiView.attributedText = self.attributedText
        } else {
            uiView.text = self.attributedText
        }

        // Compute the desired height for the content
        let fixedWidth = uiView.frame.size.width
        let newSize = uiView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))

        DispatchQueue.main.async {
            self.desiredHeight = newSize.height
        }
    }

    class Coordinator : NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ view: TextView) {
            self.parent = view
        }

        func textViewDidEndEditing(_ textView: UITextView) {
            DispatchQueue.main.async {
                self.parent.text = textView.text
                self.parent.attributedText = textView.attributedText
            }
        }
    }
}

关键是desiredHeight的绑定,它是在updateUIView中使用UIView sizeThatFits方法计算出来的。请注意,它包装在 DispatchQueue.main.async 块中,以避免 SwiftUI“在视图更新期间修改状态”错误。

我现在可以在 ContentView 中使用此视图:

struct ContentView: View {

    @State private var notes: [String?] = [
        "This is a short Note",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet consectetur. Morbi enim nunc faucibus a. Nunc pulvinar sapien et ligula ullamcorper malesuada proin libero.",
    ]

    @State private var desiredHeight: [CGFloat] = [0, 0]

    var body: some View {
        List {
            ForEach(0..<notes.count, id: \.self) { index in
                TextView(
                    desiredHeight: self.$desiredHeight[index],
                    text: self.$notes[index],
                    attributedText: .constant(nil)
                )
                .frame(height: max(self.desiredHeight[index], 100))
            }
        }
    }
}

这里,我在 String 数组中有几个注释,以及要绑定到 TextView 的desiredHeight 值数组。 TextView 的高度在 TextView 的框架修改器中设置。在此示例中,我还设置了最小高度,以便为初始编辑提供一些空间。仅当状态值之一(在本例中为注释)发生更改时,框架高度才会更新。在这里 TextView 的实现中,只有在文本视图上编辑结束时才会发生这种情况。

我尝试更新协调器中 textViewDidChange 委托函数中的文本。这会在您添加文本时更新框架高度,但使您只能在 TextView 的末尾键入文本,因为更新视图会将插入点重置到末尾!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UITextView - 根据 SwiftUI 中的内容调整大小 的相关文章

随机推荐

  • Restangular 是否支持 withCredentials 选项和 cors 请求的其他选项?

    我正在谷歌搜索 但没有找到任何线索 矩形是否支持凭证选项以及 cors 请求的其他选项 我的意思是我可以在 cors 调用中使用它而没有任何问题吗 你能帮我吗 是的 它确实 您可以通过使用来设置它们setDefaultHttpFields
  • 不同 Logback 附加程序的特定于包的日志记录级别

    我有这个简单的 Logback 配置文件 其中包含两个附加程序和一些基于包名称的自定义日志记录级别
  • 点符号与 $elemMatch

    我有一个 unitScores 集合 其中每个文档都有一个 id 和一个文档数组 如下所示 id ObjectId 52134edd5b1c2bb503000001 scores userId ObjectId 5212bf3869bf35
  • PHPStorm 中是否可以实现 Ruby 语法高亮显示?

    I found this但老实说不确定如何安装它或它是否适用 谢谢 您链接的 Ruby 插件仅为 IntelliJ IDEA Ultimate 设计 它不适用于 PhpStorm 看这个答案更多细节 但是 可以使用 PhpStorm 中的
  • 在循环之前或循环中声明变量之间的区别?

    我一直想知道 一般来说 在循环之前声明一个一次性变量 而不是在循环内重复声明 是否会产生任何 性能 差异 A 完全没有意义 Java 中的示例 a 循环前声明 double intermediateResult for int i 0 i
  • 确定 GAM 平滑对象的导数

    我有一个非常简单的时间序列数据集 由单个变量的年平均值 AVERAGE 组成 我希望研究时间序列 趋势 分量的变化率 一阶导数 和加速度 二阶导数 以及相关的标准误差 我使用 MGCV 的 GAM 和 PREDICT 函数获得了 趋势 如下
  • 核心数据内存使用和内存警告

    我有这个问题 我在核心数据中有一个图像数据库 我获取所有图像 大约 80MB 并放入 NSMutableArray 中 对象被正确错误 NSArray fetchResults self managedObjectContext execu
  • Unity PerRequestLifetimeManager 在不同请求中重用对象

    我已经为我们的项目设置了 Unity 的依赖注入 该项目本身是一个同时使用 MVC 和 Web API 的 ASP NET 应用程序 对于数据库上下文 我正在使用PerRequestLifetimeManager 这样做是为了使业务逻辑的不
  • wpf - 我可以在 wpf 中使用 System.Drawing 吗?

    我正在将图像保存在数据库中 但是如何从数据库中检索该图像 当我尝试使用system drawing 它显示错误 一些人说我不能在wpf中使用system drwaing 甚至不能使用dll文件 我的代码是 private void btnS
  • 子 pom 中存在重复的artifactId

    我希望父 pom 为众多子 pom 定义一些要继承的属性 但是 当我尝试在父 pom 中的这些属性之一中使用 artifactId 时 它会在子项的有效 pom 中重复 下面是非常基本的示例 假设我拥有 poms 所需的所有有效字段 gro
  • ModelSim-Altera 错误

    我正在使用 Ubuntu Linux 14 04 LTS 和 Altera Quartus 15 0 网络版 由于许可错误 我很难模拟我的设计 我正在设计一个 LCD driverVEEK MT友晶科技的液晶触摸屏旋风 IV EP4CE11
  • 如何使用freopen_s函数

    为了从文本文件读取输入 我编写了以下代码 int main int x ifndef ONLINE JUDGE freopen input txt r stdin endif scanf d x printf d n x system pa
  • 为什么“git clone”不采用 refspec?

    看来很多人都去换了git clone与组合git init git fetch 这看起来相当愚蠢 不幸的是像 Jenkins 这样的工具不会为你做这件事 那么为什么 git clone 不像 git fetch 那样采用 refspec 呢
  • 如何在 Ruby 中获取 Enumerable 的第 n 个元素

    例如 要返回第 10 000 个质数 我可以编写 require prime Prime first 10000 last gt 104729 但是创建一个巨大的中间数组 只是为了检索它的最后一个元素感觉有点麻烦 鉴于 Ruby 是一种如此
  • 强制调用父方法

    是否有 或模式 强制调用父方法 我有一个像这样的抽象类 abstract class APrimitive public function validate Do some stuff that applies all classes th
  • 多个main方法有什么用?

    c 使我们能够使用方法定义多个类 Main方法是程序执行的入口点 那么为什么我们要拥有多个地方来执行程序呢 多个 main 方法相对于单个 main 方法有什么优点 Edit 示例 cs Class Example 1 public sta
  • 打字稿用只读属性初始化对象

    有没有办法初始化对象文字并同时声明其具有只读属性的接口 例如 let a readonly b 2 readonly c 3 您可以使用as const断言 let a b 2 c 3 as const typed as readonly
  • 为什么我的异步 ASP.NET Web API 控制器阻塞主线程?

    我有一个 ASP NET Web API 控制器thought将异步操作 控制器设计为在第一个请求时休眠 20 秒 但立即为任何后续请求提供服务 所以我预计的时间表是这样的 提出要求1 提出要求2 提出要求3 要求 2 次退货 请求 3 个
  • 如何在 Ruby 中交错不同长度的数组

    如果我想在 Ruby 中交错一组数组 并且每个数组的长度相同 我们可以这样做 a zip b zip c flatten 但是 如果数组的大小可以不同 我们如何解决这个问题呢 我们可以做这样的事情 def interleave args r
  • UITextView - 根据 SwiftUI 中的内容调整大小

    我试图弄清楚如何使 UITextView 的大小取决于它在 SwiftUI 中的内容 我将 UITextView 包裹在UIViewRepresentable如下 struct TextView UIViewRepresentable Bi