gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 23:51:00 25 4
gpt4 key购买 nike

我试图弄清楚如何使 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
}
}
}
}

关键是desiredHeight的绑定(bind),它是在updateUIView中使用UIView sizeThatFits方法计算出来的。请注意,它包装在 DispatchQueue.main.async block 中,以避免 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))
}
}
}
}

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

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

关于ios - UITextView - 根据 SwiftUI 中的内容调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58670201/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com