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

我试图找出如何使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中的帧大小,但没有任何效果。我想在这个阶段, View 甚至没有布局,并且其框架在其他地方被覆盖。如果有人能指出我正确的方向,我将不胜感激。

最佳答案

我可以通过在TextView中绑定(bind)一个变量来使其工作,该变量被封装 View 用来设置框架高度。这是最小的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
            }
        }
    }
}


关键是期望高度的绑定(bind),该绑定(bind)是使用UIView sizeThatFits方法在updateUIView中计算的。请注意,这被包装在DispatchQueue.main.async块中,以避免SwiftUI“在 View 更新期间修改状态”错误。

我现在可以在ContentView中使用此 View :
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数组中有一些注意事项,以及要绑定(bind)到TextView的desireHeight值数组。 TextView的高度在TextView的frame修改器中设置。在此示例中,我还设置了最小高度,以便为初始编辑留出一些空间。仅当状态值之一(在本例中为注释)更改时,框架高度才会更新。在此处的TextView的实现中,仅当编辑在文本 View 上结束时才会发生这种情况。

我尝试更新Coordinator中的textViewDidChange委托(delegate)函数中的文本。这将在您添加文本时更新框架高度,但是这样做可以使您只能在TextView的末尾键入文本,因为更新 View 会将插入点重置为末尾!                                                                                                                                     

android - 如何使用 GPUimage 将多个过滤器应用于 Android 中的同一图像? - 程序调试信息网

终止linux进程的命令是什么,Linux命令-终止进程命令:kill - 程序调试信息网

linux查找进程的pid,并且kill - 程序调试信息网

asp.net - 网站项目的已编译dll在哪里 - 程序调试信息网

段式LCD原理 - 程序调试信息网

glsl - 如何访问 glsl mat4 的各个元素? - 程序调试信息网

Chart.js - 增加图例和图表之间的间距 - 程序调试信息网

java - 当我使用“FileUtils.copyURLToFile(urlConnection.getURL(),exportFile);”时出现IO异常 - 程序调试信息网

sql - 如何在不删除的情况下更改列 nvarchar 长度 - 程序调试信息网

可执行程序 段式内存管理 - 程序调试信息网

linux查看进程内存泄露,linux进程调试和内存泄露查看 - 程序调试信息网

拥有10年编程经验的你,为什么还一直停留在原地 - 程序调试信息网

ZT 线程的分离状态 2012-08-16 17:00:59 - 程序调试信息网

深度好文:Linux系统内存知识 - 程序调试信息网

json-ld - @context 中的 json-ld @id 和 @type 有什么区别? - 程序调试信息网

java - 命令行参数中的*问题 - 程序调试信息网

实验题目:linux内核编模块编程 - 程序调试信息网

parsing - 解决LALR解析器中的移位减少冲突 - 程序调试信息网

linux回收内存的方法,linux释放内存的方法 - 程序调试信息网

gcc - 如果在某个日期之后编译,则预处理器宏将删除代码 - 程序调试信息网

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值