You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI待办APP实现Sheet与键盘同步动画显示的方案咨询

SwiftUI待办应用:Sheet与键盘同步动画+自动聚焦解决方案

核心实现思路

通过监听Sheet的呈现状态,在Sheet开始显示的同时触发TextField聚焦,配合异步调度确保动画同步,避免之前onAppear/task等待Sheet完全显示才触发键盘的滞后问题。

完整代码示例

import SwiftUI

struct TodoListView: View {
    @State private var isShowingAddSheet = false
    @State private var newTodoContent = ""
    // 聚焦状态绑定到Sheet内的TextField
    @FocusState private var isInputFocused: Bool
    
    var body: some View {
        NavigationStack {
            List {
                // 这里放置你的待办列表内容
            }
            .navigationTitle("待办事项")
            .toolbar {
                Button("Add") {
                    isShowingAddSheet = true
                }
            }
            .sheet(isPresented: $isShowingAddSheet) {
                AddTodoSheet(content: $newTodoContent, isFocused: $isInputFocused)
                    // 设置Sheet为固定部分高度
                    .presentationDetents([.height(220)])
                    .presentationDragIndicator(.visible)
            }
            // 监听Sheet的显示状态变化
            .onChange(of: isShowingAddSheet) { isPresenting in
                if isPresenting {
                    // 异步调度,让Sheet先启动动画再触发聚焦,实现同步
                    DispatchQueue.main.async {
                        isInputFocused = true
                    }
                } else {
                    // 关闭Sheet时重置状态
                    isInputFocused = false
                    newTodoContent = ""
                }
            }
        }
    }
}

struct AddTodoSheet: View {
    @Binding var content: String
    @FocusState.Binding var isFocused: Bool
    // 环境变量用于关闭Sheet
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        VStack(spacing: 18) {
            TextField("输入待办内容", text: $content)
                .textFieldStyle(.roundedBorder)
                .focused($isFocused)
            
            HStack {
                Button("取消") {
                    dismiss()
                }
                Spacer()
                Button("保存") {
                    // 在这里添加保存待办事项的逻辑
                    dismiss()
                }
                .disabled(content.trimmingCharacters(in: .whitespaces).isEmpty)
            }
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 16)
    }
}

关键细节说明

  1. 聚焦时机控制:放弃在Sheet内部的onAppear/task触发聚焦,转而在父视图监听Sheet的isPresented状态变化。当Sheet开始显示时,用DispatchQueue.main.async延迟极短时间触发聚焦——这个延迟能让SwiftUI先启动Sheet的滑入动画,再同步触发键盘弹出动画,实现视觉上的流畅同步。
  2. 绑定状态管理:将@FocusState提升到父视图,通过绑定传递给Sheet,确保状态变更能及时触发,不需要等待Sheet视图完全初始化。
  3. Sheet配置:使用presentationDetents设置固定高度,配合presentationDragIndicator保留Sheet的原生交互体验,同时避免Sheet高度随键盘自动变化导致的动画冲突。

关于键盘辅助视图的补充

你提到的.toolbar方案更适合在键盘上方附加操作按钮,而非承载输入框本身。聊天类APP的底部输入栏通常是通过监听键盘高度变化,动态调整视图位置实现的,和你需要的Sheet场景逻辑不同,上述方案更贴合待办应用的添加流程需求。

内容的提问来源于stack exchange,提问作者Dave Feldman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 14:45:33