Open onmyway133 opened 3 years ago
This can be used in message bar input or some popover form. We use sizeThatFits to calculate the height so that it grow under certain height limit
sizeThatFits
import SwiftUI import UIKit struct MessageTextField: View { let placeholder: String @Binding var text: String @Binding var isEditing: Bool @State private var height: CGFloat = 100 var body: some View { UITextViewWrapper( text: $text, isEditing: $isEditing, height: $height ) .frame(height: height) .background(placeholderView, alignment: .topLeading) } var placeholderView: some View { Group { if text.isEmpty { Text(placeholder) .foregroundColor(Asset.textSecondary.color) .font(.system(size: 16)) .padding(.leading) } } } } private struct UITextViewWrapper: UIViewRepresentable { typealias UIViewType = UITextView @Binding var text: String @Binding var isEditing: Bool @Binding var height: CGFloat private static let maxHeight: CGFloat = 100 func makeUIView(context: Context) -> UITextView { let textField = UITextView() textField.delegate = context.coordinator textField.isEditable = true textField.font = UIFont.systemFont(ofSize: 16) textField.isSelectable = true textField.isUserInteractionEnabled = true textField.isScrollEnabled = true textField.backgroundColor = UIColor.clear textField.textColor = .textPrimary textField.tintColor = .textPrimary textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) return textField } func updateUIView(_ uiView: UITextView, context: Context) { if uiView.text != text { uiView.text = text } calculateHeight(view: uiView) } private func calculateHeight( view: UIView ) { let size = view.sizeThatFits( CGSize( width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude ) ) guard height != size.height else { return } DispatchQueue.main.async { height = min(size.height, Self.maxHeight) } } func makeCoordinator() -> Coordinator { Coordinator(parent: self) } final class Coordinator: NSObject, UITextViewDelegate { let parent: UITextViewWrapper init(parent: UITextViewWrapper) { self.parent = parent } func textViewDidChange(_ uiView: UITextView) { parent.text = uiView.text } func textViewDidBeginEditing(_: UITextView) { parent.isEditing = true } func textViewDidEndEditing(_: UITextView) { parent.isEditing = false } } }
This can be used in message bar input or some popover form. We use
sizeThatFits
to calculate the height so that it grow under certain height limit