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
相关产品推荐
相关产品推荐

