iOS13 发现 TextField 没有任何类型的键盘避免处理。因此,我们创建了运行良好的键盘避免机制。我们升级到 iOS14,这导致 TextFields 内置了键盘避免功能。但是,键盘避免功能似乎没有按预期工作。
问题 1 我们遇到的第一个问题是键盘避免在屏幕中心和周围的文本字段中无法正常工作。鉴于此代码:
struct ContentView: View {
@State var text:String = ""
var body: some View {
TextField("Testing", text: $text)
}
}
Run Code Online (Sandbox Code Playgroud)
在 iPhone 8 Plus 上,文本字段向上移动。我们认为这不应该发生,因为 TextField 不会被键盘隐藏,因此它应该保留在同一位置。
问题 1: 这是一个错误,应该向 Apple 报告吗?我们认为这是一个错误/问题。
我们发现使用以下方法:
struct ContentView: View {
@State var text:String = ""
var body: some View {
VStack {
Spacer()
TextField("Testing", text: $text)
}
}
}
Run Code Online (Sandbox Code Playgroud)
TextField 将移动到键盘正上方。这是预期的行为。我们还发现使用以下代码:
struct ContentView: View {
@State var text:String = ""
var body: some View {
VStack {
TextField("Testing", text: $text)
Spacer()
}
}
}
Run Code Online (Sandbox Code Playgroud)
TextField 不会移动,因为它永远不会被 TextField 覆盖。再一次,这是我们期望的行为。但是,屏幕中心内和周围的任何 TextField 似乎键盘避免将 TextField 移动到它不应该移动的场景中。
问题 2
我们的应用程序在某些屏幕的中心和周围保留了 TextFields,因此上面发现的问题只会增加糟糕的用户体验,因此我们希望“关闭”提供给我们的这种键盘避免功能。我们希望使用ignoresSafeArea修饰符如下:
struct ContentView: View {
@State var text:String = ""
var body: some View {
if #available(iOS 14.0, *) {
VStack {
TextField("Testing", text: $text)
}
.ignoresSafeArea(.keyboard, edges: .bottom)
} else {
// Fallback on earlier versions
// Our iOS13 Code
}
}
}
Run Code Online (Sandbox Code Playgroud)
观察到的结果是修饰符根本不起作用。TextField 仍然向上移动。但是,当使用这样的东西时:
struct ContentView: View {
@State var text:String = ""
var body: some View {
if #available(iOS 14.0, *) {
VStack {
Spacer()
TextField("Testing", text: $text)
}
.ignoresSafeArea(.keyboard, edges: .bottom)
} else {
// Fallback on earlier versions
// Our iOS13 Code
}
}
}
Run Code Online (Sandbox Code Playgroud)
该ignoresSafeArea作品,因此这导致了第二个问题:
问题 2ignoresSafeArea修改器
是否也有错误?这是应该报告的事情吗?
屏幕中心及其周围的 TextField 似乎存在潜在问题?
问题 3 有人知道解决这些问题的方法吗?因为现在它是 iOS14 上的一个大问题。键盘回避不起作用,任何尝试关闭它的尝试也不起作用。
我们使用的是 Xcode 12.0 (12A7209)
更新
我们发现将 TextField 包装在 Geometry Reader 中,这似乎“关闭”了 TextField 的键盘回避。然而,我们认为这是一个令人愉快的 hack,它以一种方式解决了问题,但同时也暴露了键盘回避在几何阅读器中不起作用,这可能是其他人的错误/问题......
struct ContentView: View {
@State var text:String = ""
var body: some View {
if #available(iOS 14.0, *) {
GeometryReader { _ in
VStack {
Spacer().frame(height:500) //Compensate for other Views in the Stack
TextField("Testing", text: $text)
}
}
} else {
// Fallback on earlier versions
// Our iOS13 Code
}
}
}
Run Code Online (Sandbox Code Playgroud)
Cos*_*syn 10
您描述的行为都是预期的。我们需要明白三件事:
(1) SwiftUI 布局系统中最相关的概念是视图可以具有固定大小或灵活大小。例如,单行文本具有固定大小。所以只有文本的 VStack 也有固定的大小。尝试这个
struct ContentView: View {
var body: some View {
VStack {
Text("Hello")
Text("World")
}
.border(Color.green)
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到绿色边框仅环绕文本。
另一方面,Spacers, Colors, GeometryReaders 等具有灵活的尺寸,它们往往会扩展以占据所有可用空间。
(2) 当键盘显示时,容器上有一个安全区域。容器的高度将降低。
(3) ignoresSafeArea 修饰符通常应用于具有灵活高度的视图。以底部边缘为例,只有当视图的原始底部边缘刚好与底部安全区域的顶部边缘对齐或被底部安全区域覆盖时,修改器才会起作用。因此,如果视图的底部边缘远离底部安全区域的顶部边缘,则 ignoresSafeArea 将不起作用。
现在我将解释为什么你所有的例子都有预期的行为。
示例 1
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextField("Testing", text: $text)
}
}
Run Code Online (Sandbox Code Playgroud)
行为:即使没有被键盘覆盖,当键盘显示时,文本字段也会向上移动一点。
原因:安全区在容器上,当键盘显示时,容器高度降低。由于文本字段位于容器的中心,因此它会向上移动一点。
示例 2
struct ContentView: View {
@State var text: String = ""
var body: some View {
VStack {
Spacer()
TextField("Testing", text: $text)
}
}
}
Run Code Online (Sandbox Code Playgroud)
行为:当键盘显示时,文本字段移动到键盘正上方。
原因:VStack里面有一个Spacer,所以VStack的高度会一直延伸到容器提供的高度。当容器的高度因键盘而降低时,VStack 的高度也随之降低。
示例 3
struct ContentView: View {
@State var text: String = ""
var body: some View {
VStack {
TextField("Testing", text: $text)
}
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
Run Code Online (Sandbox Code Playgroud)
行为:当键盘显示时,文本字段会向上移动一点。ignoresSafeArea 修饰符没有任何效果。
原因:在VStack上应用了ignoresSafeArea,而VStack的高度是固定的,而且它的底边离底部安全区很远,ignoresSafeArea没有效果。但是容器并没有忽略SafeArea,所以当键盘显示时容器的高度仍然降低。
示例 4
struct ContentView: View {
@State var text: String = ""
var body: some View {
VStack {
Spacer()
TextField("Testing", text: $text)
}
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
Run Code Online (Sandbox Code Playgroud)
行为:键盘显示时文本字段不移动,ignoresSafeArea 正在工作。
原因:这次 Spacer 会让 VStack 扩展它的高度。请记住,容器不会忽略安全区域,因此如果未应用 ignoresSafeArea 修饰符,当键盘显示时,VStack 的底部边缘将与底部安全区域的顶部边缘对齐。所以这一次如果应用了ignoresSafeArea,它就会起作用并使VStack扩展其高度以忽略键盘底部安全区域。
另一个示例可以帮助您了解父视图如何尊重安全区域而子视图可以忽略它们。
示例 5:
struct ContentView: View {
var body: some View {
ZStack {
Color.yellow
Color.green
.frame(width: 200)
.ignoresSafeArea()
}
.border(Color.blue, width: 10)
}
}
Run Code Online (Sandbox Code Playgroud)
行为:
从蓝色边框,我们看到父 ZStack 尊重安全区域,而绿色子视图忽略安全区域。
要关闭 iOS 14 键盘回避,您可以将 ignoresSafeArea 应用于扩展其高度的父视图,例如
struct ContentView: View {
@State var text: String = ""
var body: some View {
ZStack {
Color.clear
VStack {
TextField("Testing", text: $text)
}
}
.ignoresSafeArea(.keyboard)
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,Color.clear 扩展了它的高度,使 ZStack 扩展了它的高度,因此 ZStack 将忽略键盘安全区域。VStack 位于 ZStack 的中心,因此不受键盘的影响。
| 归档时间: |
|
| 查看次数: |
5181 次 |
| 最近记录: |