atd*_*nsm 6 swiftui uiviewrepresentable
我非常接近在 SwiftUI 中实现 UITextView 的动态高度。请帮我解决这些问题:
[SwiftUI] Modifying state during view update, this will cause undefined behavior.这是我的代码:
项目编辑视图
TextView(text: $notes, textViewHeight: $textViewHeight)
.frame(height: self.textViewHeight)
Run Code Online (Sandbox Code Playgroud)
UI文本视图
import SwiftUI
struct TextView: UIViewRepresentable {
@Binding var text: String
@Binding var textViewHeight: CGFloat
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
textView.font = .systemFont(ofSize: 17)
textView.backgroundColor = .clear
return textView
}
func updateUIView(_ textView: UITextView, context: Context) {
textView.text = text
}
class Coordinator: NSObject, UITextViewDelegate {
var control: TextView
init(_ control: TextView) {
self.control = control
}
func textViewDidChange(_ textView: UITextView) {
control.text = textView.text
}
}
func makeCoordinator() -> TextView.Coordinator {
Coordinator(self)
}
}
Run Code Online (Sandbox Code Playgroud)
有人问过类似的问题,但没有一个解决方案对我有用。
小智 6
For anyone who comes across this thread in the future. I researched through the suggested answers and to me they weren't ideal. As of iOS 16, UIViewRepresentable has a overridable function sizeThatFits, this function will allow you to calculate the size of the resulting SwiftUI view using the proposed parent dimensions. Example below:
func sizeThatFits(_ proposal: ProposedViewSize, uiView: UITextView, context: Context) -> CGSize? {
let dimensions = proposal.replacingUnspecifiedDimensions(
by: .init(
width: 0,
height: CGFloat.greatestFiniteMagnitude
)
)
let calculatedHeight = calculateTextViewHeight(
containerSize: dimensions,
attributedString: uiView.attributedText
)
return .init(
width: dimensions.width,
height: calculatedHeight
)
}
private func calculateTextViewHeight(containerSize: CGSize,
attributedString: NSAttributedString) -> CGFloat {
let boundingRect = attributedString.boundingRect(
with: .init(width: containerSize.width, height: .greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin, .usesFontLeading],
context: nil
)
return boundingRect.height
}
Run Code Online (Sandbox Code Playgroud)
Note: For this calculation method to work correctly, you may need to update the UITextView properties in the makeUIView function:
textView.textContainer.lineFragmentPadding = 0
textView.textContainerInset = .zero
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5208 次 |
| 最近记录: |