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

SwiftUI如何实现点击按钮后展示对应下一级选项按钮

SwiftUI 实现长链式层级选择按钮交互

要实现点击按钮切换下一级选项组的链式选择流程,不需要硬编码多套页面和跳转逻辑,用树形数据结构+状态驱动动态渲染按钮即可,后续扩展任意层级的选项只需要修改数据配置,不用重复写布局代码。

核心实现逻辑

  • 定义嵌套的选项数据结构,每个选项节点保存自身显示文本、以及下一级对应的子选项列表,天然匹配长链式选择的层级关系
  • 用@State追踪当前需要渲染的选项列表,初始值为最顶层的「Countries」「States」两个按钮
  • 把原来硬编码写死的两个NavigationLink改成动态遍历当前选项数组生成,点击按钮时判断该选项是否有子选项:有子选项就把当前渲染列表替换成该选项的子选项列表,自动刷新出新的按钮组;没有子选项就代表走到选择链末端,跳转到对应业务页面即可
  • 可选增加返回上一级按钮,支持选择错误时回退

完整实现代码

import SwiftUI

// 选项节点数据结构,支持无限层级嵌套
struct OptionNode: Identifiable {
    let id = UUID()
    let title: String
    var children: [OptionNode]? = nil
}

struct ContentView: View {
    @StateObject var triviaManager = TriviaManager()
    // 追踪当前需要展示的选项组
    @State private var currentOptions: [OptionNode]
    // 追踪选择路径,用于返回上一级
    @State private var selectionPath: [[OptionNode]] = []
    
    // 初始化时配置整个链式选择的所有层级数据
    init() {
        // 最顶层选项
        let rootOptions = [
            OptionNode(title: "Countries", children: [
                OptionNode(title: "America", children: []),
                OptionNode(title: "Canada", children: [])
            ]),
            OptionNode(title: "States", children: [
                OptionNode(title: "California", children: []),
                OptionNode(title: "Nevada", children: [])
            ])
        ]
        _currentOptions = State(initialValue: rootOptions)
    }
    
    var body: some View {
        NavigationView {
            VStack(spacing: 40) {
                VStack(spacing: 20) {
                    Text("Foodie's Pick")
                        .lilacTitle()
                    
                    Text("Let's Find your Match")
                        .foregroundColor(Color("AccentColor"))
                }
                
                // 动态渲染当前层级的所有按钮
                HStack(spacing: 20) {
                    ForEach(currentOptions) { option in
                        NavigationLink {
                            // 有子选项就切换下一级选项,没有子选项就跳转到题目页
                            if option.children != nil {
                                Color.clear
                                    .onAppear {
                                        selectionPath.append(currentOptions)
                                        currentOptions = option.children ?? []
                                    }
                            } else {
                                TriviaView()
                                    .environmentObject(triviaManager)
                            }
                        } label: {
                            PrimaryButton(text: option.title)
                        }
                    }
                }
                
                // 非顶层时显示返回上一级按钮
                if !selectionPath.isEmpty {
                    Button("返回上一级") {
                        currentOptions = selectionPath.removeLast()
                    }
                    .foregroundColor(.gray)
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .edgesIgnoringSafeArea(.all)
            .background(Color(red: 1, green: 1, blue: 1))
            .navigationViewStyle(.stack)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

扩展说明

如果后续要加长选择链路,只需要在init里的对应节点下增加children数组内容即可,比如要给「California」下加「Los Angeles」「San Francisco」两个选项,直接修改对应节点:

OptionNode(title: "California", children: [
    OptionNode(title: "Los Angeles"),
    OptionNode(title: "San Francisco")
])

不需要修改任何布局和跳转逻辑,页面会自动渲染新层级的按钮组。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:21:26