You need to enable JavaScript to run this app. SwiftUI 如何实现点击可跳转不同视图的按钮网格视图
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI 如何实现点击可跳转不同视图的按钮网格视图

SwiftUI 按钮式网格视图实现方案

原代码核心问题

  • 视图结构体命名与内部属性重名,容易引发编译错误和逻辑混淆
  • 硬编码双层循环实现2*2布局,未使用数据源驱动,按钮数量调整时需要手动修改循环逻辑,扩展性差
  • 所有按钮共用同一个isActive状态,无法区分不同按钮对应的跳转目标,会出现点击任意按钮触发错误跳转的问题
  • isActive状态未绑定实际的NavigationLink跳转逻辑,状态修改后不会触发任何页面跳转
  • 按钮未设置自适应宽度,无法实现均等的网格单元格排布,样式不符合预期

优化实现方案

1. 定义按钮数据源模型

将按钮标题、目标跳转视图封装为独立模型,实现业务逻辑与视图的解耦:

import SwiftUI

/// 网格按钮数据模型
struct GridButtonItem: Identifiable {
    let id = UUID()
    let title: String
    /// 绑定对应跳转的目标视图
    let destination: AnyView
}

// 示例目标视图,可根据业务需求自定义
struct DemoViewA: View {
    var body: some View {
        Text("视图A内容")
    }
}

struct DemoViewB: View {
    var body: some View {
        Text("视图B内容")
    }
}

2. 实现自适应网格按钮视图

使用LazyVGrid替代手动嵌套的HStack/ForEach布局,通过状态绑定实现单按钮的独立跳转:

struct MainCollectionView: View {
    /// 外部传入的按钮数据源
    let items: [GridButtonItem]
    /// 当前选中的按钮ID,用于绑定跳转状态
    @State private var selectedItemID: GridButtonItem.ID?
    
    /// 网格配置:设置为2列等宽布局,可按需调整列数、间距
    private let gridColumn = [
        GridItem(.flexible(), spacing: 16),
        GridItem(.flexible(), spacing: 16)
    ]
    
    var body: some View {
        NavigationView {
            ScrollView {
                LazyVGrid(columns: gridColumn, spacing: 16) {
                    ForEach(items) { item in
                        Button {
                            // 点击时设置选中项,触发跳转
                            selectedItemID = item.id
                        } label: {
                            Text(item.title)
                                .foregroundColor(.black)
                                .padding(.vertical, 12)
                                .frame(maxWidth: .infinity) // 按钮撑满单元格宽度,实现对齐
                                .background(
                                    Capsule()
                                        .strokeBorder(.white, lineWidth: 1.25)
                                )
                        }
                    }
                }
                .padding(16)
            }
            // 绑定跳转逻辑,避免直接显示可见的NavigationLink
            .background(
                NavigationLink(
                    destination: selectedItemID != nil 
                    ? items.first(where: { $0.id == selectedItemID })!.destination 
                    : AnyView(EmptyView()),
                    isActive: Binding(
                        get: { selectedItemID != nil },
                        set: { if !$0 { selectedItemID = nil } }
                    ),
                    label: { EmptyView() }
                )
            )
            .navigationTitle("功能导航")
        }
    }
}

3. 调用示例

只需要构造对应的按钮数据源,传入视图即可完成调用:

struct MainCollectionView_Previews: PreviewProvider {
    static var previews: some View {
        // 构造按钮列表,每个条目绑定对应跳转视图
        let demoItems = [
            GridButtonItem(title: "功能入口1", destination: AnyView(DemoViewA())),
            GridButtonItem(title: "功能入口2", destination: AnyView(DemoViewB())),
            GridButtonItem(title: "功能入口3", destination: AnyView(DemoViewA())),
            GridButtonItem(title: "功能入口4", destination: AnyView(DemoViewB()))
        ]
        return MainCollectionView(items: demoItems)
    }
}

方案优势

  • 布局自适应:调整列数、间距只需要修改gridColumn配置,不需要手动调整嵌套循环逻辑
  • 扩展性强:新增按钮只需要往items数组中添加对应条目即可,不需要修改视图主体逻辑
  • 跳转逻辑准确:通过选中项ID绑定跳转目标,不会出现多按钮共用状态导致的跳转错乱
  • 样式统一:按钮自动撑满单元格宽度,网格对齐效果符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 12:45:03