SwiftUI中执行.onSubmit时键盘抖动,如何保持键盘激活状态?
解决SwiftUI中提交条目时键盘抖动的问题
问题根源在于:当你在List的ForEach后放置TextField时,每次提交新条目,List会重新渲染并调整TextField的位置,导致焦点短暂丢失后又恢复,从而引发键盘抖动。
方案一:将TextField移至List Footer(推荐)
把输入框放在列表的footer区域,这样即使列表元素增加,输入框的位置相对稳定,不会因为列表布局突变导致焦点波动。同时配合异步设置焦点,确保键盘持续激活:
import SwiftUI struct ContentView: View { @FocusState private var isFocused: Bool @State private var text: String = "" @State private var items: [String] = ["Item1", "Item2"] var body: some View { VStack { List { ForEach(items, id: \.self) { item in Text(item) } } .listStyle(PlainListStyle()) .listFooter { TextField("Add item", text: $text) .focused($isFocused) .onSubmit { // 过滤空输入 let trimmedText = text.trimmingCharacters(in: .whitespaces) guard !trimmedText.isEmpty else { return } items.append(trimmedText) text = "" // 异步设置焦点,等待布局更新完成 DispatchQueue.main.async { isFocused = true } } } } .onAppear { // 页面加载时自动激活输入框 isFocused = true } } } #Preview { ContentView() }
方案二:保留原有结构,异步延迟设置焦点
如果需要维持TextField在列表内的布局,可以通过微小的延迟让List完成布局调整后再重新聚焦,避免抖动:
修改原代码中的onSubmit闭包:
.onSubmit { let trimmedText = text.trimmingCharacters(in: .whitespaces) guard !trimmedText.isEmpty else { return } items.append(trimmedText) text = "" // 延迟0.05秒再设置焦点,给List足够时间完成布局更新 DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { isFocused = true } }
两种方案都能实现键盘持续激活、无抖动的效果,方案一的稳定性更好,更符合iOS列表的交互习惯。
内容的提问来源于stack exchange,提问作者Sebbie_O
相关产品推荐
相关产品推荐

