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

如何解决SwiftUI中Sheet继承父视图键盘工具栏按钮无法收起自身键盘问题

问题根因

Sheet内键盘工具栏不生效、绑定父视图焦点状态的原因有两个:

  1. 原代码将Sheet内的.toolbar键盘工具栏修饰符错误挂载在Dismiss Sheet按钮上,没有挂载到包含TextField的根视图层级,系统无法将该工具栏配置和Sheet内的输入框建立关联。
  2. 弹出的Sheet默认未嵌入导航容器,系统检索当前输入场景对应的键盘工具栏时,会沿响应链向上查找,找不到Sheet级别的有效配置时,会直接复用底层父视图的键盘工具栏,导致按钮永远绑定父视图的focusedField1状态。
修复步骤
  • 给Sheet根内容包裹NavigationStack(iOS16+适用,旧版本可替换为NavigationView),让工具栏配置归属当前Sheet的独立导航场景,和父视图场景隔离
  • 将Sheet内的.toolbar修饰符从子按钮上移动到Sheet根视图/导航容器层级,确保系统能在当前输入场景下检索到对应的工具栏配置
修复后可运行代码
import SwiftUI

struct ContentView: View {
    @FocusState private var focusedField1: Bool
    @State private var name1 = ""
    @State private var showSheet = false
    
    var body: some View {
        NavigationStack {
            VStack {
                TextField("Hello", text: $name1)
                    .focused($focusedField1)
                    .textFieldStyle(.roundedBorder)
                    .padding()
                Button("Show Sheet") { showSheet = true }
            }
            .toolbar {
                toolBarContent1()
            }
        }
        .sheet(isPresented: $showSheet) {
            NavigationStack {
                MySheet()
            }
        }
    }
    
    @ToolbarContentBuilder func toolBarContent1() -> some ToolbarContent {
        ToolbarItemGroup(placement: .keyboard) {
            Spacer()
            Button {
               print("父视图工具栏触发")
               focusedField1 = false
            } label: { Text("Dismiss Keyboard") }
        }
    }
}

struct MySheet: View {
    @Environment(\.dismiss) var dismiss
    @FocusState private var focusedField2: Bool
    @State private var name2 = ""
    
    var body: some View {
        VStack {
            TextField("Hello", text: $name2)
                .focused($focusedField2)
                .textFieldStyle(.roundedBorder)
                .padding()
            Button("Dismiss Sheet") {
                focusedField2 = false
                dismiss()
            }
        }
        .toolbar {
            toolBarContent2()
        }
    }
    
    @ToolbarContentBuilder func toolBarContent2() -> some ToolbarContent {
         ToolbarItemGroup(placement: .keyboard) {
             Spacer()
             Button {
                print("Sheet内工具栏触发")
                focusedField2 = false
             } label: { Text("Dismiss Keyboard") }
         }
    }
}

补充:如果是多输入框、多层弹窗场景,只要保证每个独立场景的FocusState和对应键盘工具栏配置处于同一个导航作用域内,系统会自动匹配当前激活输入框所属场景的工具栏逻辑,不会出现跨层绑定焦点的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:06:43