![](/img/trans.png)
[英]SwiftUI TextEditor View content is hidden behind Navigation Bar
[英]SwiftUI TextEditor Initial Content Size Is Wrong
iOS 14.4 + Xcode 12.4
我想在 iOS 上的 SwiftUI 中制作一個簡單的清單,其中每個項目的文本都是TextEditor
。
首先,我創建了基本的應用程序結構並用一些演示內容填充它:
import SwiftUI
@main
struct TestApp: App {
@State var alpha = "Alpha"
@State var bravo = "Bravo is a really long one that should wrap to multiple lines."
@State var charlie = "Charlie"
init(){
//Remove the default background of the TextEditor/UITextView
UITextView.appearance().backgroundColor = .clear
}
var body: some Scene {
WindowGroup {
ScrollView{
VStack(spacing: 7){
TaskView(text: $alpha)
TaskView(text: $bravo)
TaskView(text: $charlie)
}
.padding(20)
}
.background(Color.gray)
}
}
}
然后每個TaskView
代表列表中的一個任務(白框):
struct TaskView:View{
@Binding var text:String
var body: some View{
HStack(alignment:.top, spacing:8){
Button(action: {
print("Test")
}){
Circle()
.strokeBorder(Color.gray,lineWidth: 1)
.background(Circle().foregroundColor(Color.white))
.frame(width:22, height: 22)
}
.buttonStyle(PlainButtonStyle())
FieldView(name: $text)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(EdgeInsets(top:10, leading:10, bottom: 10, trailing: 30))
.background(Color.white)
.cornerRadius(5)
}
}
最后,每個TextEditor
都在FieldView
中,如下所示:
struct FieldView: View{
@Binding var name: String
var body: some View{
ZStack{
Text(name)
.padding(EdgeInsets(top: -7, leading: -3, bottom: -5, trailing: -3))
.opacity(0)
TextEditor(text: $name)
.fixedSize(horizontal: false, vertical: true)
.padding(EdgeInsets(top: -7, leading: -3, bottom: -5, trailing: -3))
}
}
}
正如您在上面的屏幕截圖中看到的, TextEditor
的初始高度不會自動調整大小以適應文本。 但是一旦我輸入它,它就會適當地調整大小。 這是一個視頻,顯示:
如何讓視圖具有正確的初始高度? 在我輸入之前, TextEditor
會垂直滾動,因此它似乎具有錯誤的內在內容大小。
注意:視圖是半透明的,帶有邊框,因此您可以查看/調試正在發生的事情。
struct FieldView: View{
@Binding var name: String
@State private var textEditorHeight : CGFloat = 100
var body: some View{
ZStack(alignment: .topLeading) {
Text(name)
.background(GeometryReader {
Color.clear
.preference(key: ViewHeightKey.self,
value: $0.frame(in: .local).size.height)
})
//.opacity(0)
.border(Color.pink)
.foregroundColor(Color.red)
TextEditor(text: $name)
.padding(EdgeInsets(top: -7, leading: -3, bottom: -5, trailing: -7))
.frame(height: textEditorHeight + 12)
.border(Color.green)
.opacity(0.4)
}
.onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 }
}
}
struct ViewHeightKey: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = value + nextValue()
print("Reporting height: \(value)")
}
}
首先,我使用PreferenceKey
將“不可見”文本視圖的高度傳遞回視圖層次結構。 然后,我使用該值設置TextEditor
框架的高度。
請注意,視圖現在與topLeading
對齊——在您的初始示例中,不可見文本居中對齊。
我不喜歡的一件事是邊緣插圖的使用——這些感覺就像魔術數字(嗯,它們是……),我寧願有一個沒有它們的解決方案,它仍然保持Text
和TextEditor
完全對齊. 但是,這暫時有效。
這似乎有效並避免了滾動問題:
struct TaskView:View{
@Binding var text:String
@State private var textHeight : CGFloat = 40
var body: some View{
HStack(alignment:.top, spacing:8){
Button(action: {
print("Test")
}){
Circle()
.strokeBorder(Color.gray,lineWidth: 1)
.background(Circle().foregroundColor(Color.white))
.frame(width:22, height: 22)
}
.buttonStyle(PlainButtonStyle())
FieldView(text: $text, heightToTransmit: $textHeight)
.frame(height: textHeight)
.border(Color.red)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(EdgeInsets(top:10, leading:10, bottom: 10, trailing: 30))
.background(Color.white)
.cornerRadius(5)
}
}
struct FieldView : UIViewRepresentable {
@Binding var text : String
@Binding var heightToTransmit: CGFloat
func makeUIView(context: Context) -> UIView {
let view = UIView()
let textView = UITextView(frame: .zero, textContainer: nil)
textView.delegate = context.coordinator
textView.backgroundColor = .yellow // visual debugging
textView.isScrollEnabled = false // causes expanding height
context.coordinator.textView = textView
textView.text = text
view.addSubview(textView)
// Auto Layout
textView.translatesAutoresizingMaskIntoConstraints = false
let safeArea = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: safeArea.topAnchor),
textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor)
])
return view
}
func updateUIView(_ view: UIView, context: Context) {
context.coordinator.heightBinding = $heightToTransmit
context.coordinator.textBinding = $text
DispatchQueue.main.async {
context.coordinator.runSizing()
}
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
class Coordinator : NSObject, UITextViewDelegate {
var textBinding : Binding<String>?
var heightBinding : Binding<CGFloat>?
var textView : UITextView?
func runSizing() {
guard let textView = textView else { return }
textView.sizeToFit()
self.textBinding?.wrappedValue = textView.text
self.heightBinding?.wrappedValue = textView.frame.size.height
}
func textViewDidChange(_ textView: UITextView) {
runSizing()
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.