SwiftUI实现类似macOS提醒事项App的显示/隐藏输入文本框功能
解决方案
问题根源
当前实现存在两个错误逻辑,导致点击输入框时触发了List的全局点击手势:
gesture修饰符的including参数逻辑完全写反,editing = true时设置的.subviews会让List手势和子视图手势同时响应- 普通空
onTapGesture优先级低于上层List的手势,无法阻断手势传递
修改步骤
- 移除原来错误的
including参数配置 - 给添加任务行的容器添加高优先级的空点击手势,完全阻断上层List的手势向下传递到该行内的控件
修改后完整代码
struct ContentView: View { @State private var editing: Bool = false @State private var taskName: String = "" // 可选:添加聚焦状态实现自动唤起输入框 @FocusState private var isTextFieldFocused: Bool var body: some View { List { ForEach(1...5, id: \.self) { index in Text("\(index)") } if editing { VStack(alignment: .leading) { TextField("Enter task", text: $taskName) .focused($isTextFieldFocused) HStack { Button("Add Date") { }.buttonStyle(.bordered) Button("Add Location") { }.buttonStyle(.bordered) } } // 高优先级空手势阻断上层List的点击手势传递 .highPriorityGesture(TapGesture()) // 可选:行出现时自动激活输入框,贴合官方交互 .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { isTextFieldFocused = true } } } } .listStyle(.plain) .gesture( TapGesture().onEnded({ _ in withAnimation { editing.toggle() } }) ) // 可选:输入完成按回车自动收起添加行 .onSubmit { guard !taskName.isEmpty else { return } // 这里添加保存任务逻辑 taskName = "" editing = false } } }
效果说明
修改后交互完全匹配官方提醒事项:
- 点击列表任意非添加行区域,都会触发添加行的显示/隐藏
- 点击添加行内的输入框、按钮,都不会触发上层手势,添加行不会意外收起
- 可选添加的自动聚焦、回车提交逻辑完全贴合原生交互
内容的提问来源于stack exchange,提问作者Mary Doe
相关产品推荐
相关产品推荐

