在表单中扩展SwiftUI的TextEditor以利用剩余空间。

huangapple go评论66阅读模式
英文:

Extend SwiftUI's TextEditor within Form to use remaining space

问题

我正在使用一个表单内的TextEditor。一个最简单的示例如下:

import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    @State var text = String()
    
    var body: some View {
        Form {
            Section("Section") {
                Toggle("Toggle", isOn: .constant(true))
                LabeledContent("TextEditor") {
                    TextEditor(text: $text)
                }
            }
        }
    }
}
PlaygroundPage.current.setLiveView(ContentView())

这会渲染成类似以下的内容:

在表单中扩展SwiftUI的TextEditor以利用剩余空间。

由于TextEditor是一个多行输入字段,我希望它能扩展到屏幕上剩余的可用空间,就像下面这样:

在表单中扩展SwiftUI的TextEditor以利用剩余空间。

我可以通过向TextEditor添加.frame(height:540)修饰符来实现这一点,但这样硬编码的扩展不太灵活,因此只适用于特定的设备。

所以问题是,如何以一种在所有潜在设备上都有效的动态方式来实现这一点(不同的iPhone、iPad等)。

注意:这个问题类似于https://stackoverflow.com/questions/68486403/swiftui-texteditor-in-a-form。然而,这只解决了如何显示多行的问题,可以很容易地通过上面提到的.frame(height:X)修饰符实现。

英文:

I'm using a TextEditor inside a Form. A minimal playground example would be

import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    @State var text = String()
    
    var body: some View {
        Form {
            Section("Section") {
                Toggle("Toggle", isOn: .constant(true))
                LabeledContent("TextEditor") {
                    TextEditor(text: $text)
                }
            }
        }
    }
}
PlaygroundPage.current.setLiveView(ContentView())

This renders into something like:

在表单中扩展SwiftUI的TextEditor以利用剩余空间。

As TextEditor is a multiline input field, I'd like it to extend to the remaining available space on the screen, so something like

在表单中扩展SwiftUI的TextEditor以利用剩余空间。

I can achieve this by adding a .frame(height:540) modifier to the TextEditor, however this hardcodes the extend is not very dynamic and thus only works on a specific device.

So the question is, how to to this in a dynamic way which works on all potential devices (different iPhones, iPad, ...).

Note: This question is similar to https://stackoverflow.com/questions/68486403/swiftui-texteditor-in-a-form. However this only addresses the issue how to get it to show multiple lines, which can be easily achieved using the above mentioned .frame(height:X) modifier.

答案1

得分: 0

UISCREEN SOLUTION

import SwiftUI

struct ContentView: View {
    @State var text = String()
    
    var body: some View {
        if #available(iOS 16, *) {
            Form {
                Section("Section") {
                    Toggle("Toggle", isOn: .constant(true))
                    LabeledContent("TextEditor") {
                        TextEditor(text: $text)
                    }.frame(minHeight: UIScreen.main.bounds.maxY - 190)
                }
            }
        }
    }
}

GEOMETRY READER SOLUTION

@State var text = String()
@Environment(\.defaultMinListRowHeight) var minH

var body: some View {
    if #available(iOS 16, *) {
        GeometryReader { geometry in
            Form {
                Section("Section") {
                    Toggle("Toggle", isOn: .constant(true))
                    LabeledContent("TextEditor") {
                        TextEditor(text: $text)
                    }.frame(minHeight: geometry.size.height - minH - 70)
                }
            }
        }
    }
}

请注意蓝色轮廓 - 这是表单的大小。正如您在这三种情况下所看到的,TextField 可以达到表单的底部,而不会进入安全区域,该区域用于控制设备上的手势(在 iPhone SE 上没有手势,因此也没有安全区域)。

英文:

I don't think this is the best solution, although it works. If you want something else, try using GeometryReader with a dynamic height value stored in a CGFloat variable. (Tested on iPhone 14 Pro, 14 Pro Max and iPad 12.9 inch)

UISCREEN SOLUTION

import SwiftUI

struct ContentView: View {
    @State var text = String()
    
    var body: some View {
        if #available(iOS 16, *){
            Form {
                Section("Section") {
                    Toggle("Toggle", isOn: .constant(true))
                    LabeledContent("TextEditor") {
                        TextEditor(text: $text)
                    }.frame(minHeight: UIScreen.main.bounds.maxY-190)
                }
            }
        }
    }
}

You can also use constant points, as the points reflect different screen sizes and resolutions: https://stackoverflow.com/a/73653966/14856451

GEOMETRY READER SOLUTION

@State var text = String()
@Environment(\.defaultMinListRowHeight) var minH
var body: some View {
    if #available(iOS 16, *){
        GeometryReader {geometry in
            Form {
                Section("Section") {
                    Toggle("Toggle", isOn: .constant(true))
                    LabeledContent("TextEditor") {
                        TextEditor(text: $text)
                    }.frame(minHeight: geometry.size.height-minH-70)
                }
            }
        }
    }
}

Notice the blue outline - that's the size of your form. As you can see in all three cases, the TextField reaches the bottom of the form without going into the safe zone, which is used to control gestures on the device (there are no gestures on the iPhone SE, so there is no safe zone either).

在表单中扩展SwiftUI的TextEditor以利用剩余空间。
在表单中扩展SwiftUI的TextEditor以利用剩余空间。
在表单中扩展SwiftUI的TextEditor以利用剩余空间。

huangapple
  • 本文由 发表于 2023年2月16日 16:43:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469694.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定