Swift实现带固定表头与首列的非同步滚动表格方案问询
求实现带固定表头和首列的双向滚动表格(SwiftUI)

我尝试了很久仍未解决,由于刚接触Swift,进展更不顺利。该表格需满足以下要求:
- 支持横向和纵向滚动,但不能同时滚动(无斜向滚动)
- 拥有固定表头行(滚动至表格末尾时会被“推离”)
- 拥有固定首列
我在两款应用中见过该效果,认为实现难度应不大,但自己始终无法做好。目前我使用SwiftUI开发,考虑是否需要改用UIKit。
以下是我写的接近效果的代码:
import SwiftUI struct Team { let teamId: Int let city: String let name: String } struct ScrollableTableView: View { @State private var teams = [ Team(teamId: 1610612737, city: "Atlanta", name: "Hawks"), Team(teamId: 1610612738, city: "Boston", name: "Celtics"), Team(teamId: 1610612739, city: "Cleveland", name: "Cavaliers"), Team(teamId: 1610612740, city: "New Orleans", name: "Pelicans") ] var body: some View { let columns = [ GridItem(.fixed(120), alignment: .leading), // 固定首列 GridItem(.fixed(150), alignment: .leading), GridItem(.fixed(200), alignment: .leading) ] ScrollView([.vertical], showsIndicators: true) { ZStack { ScrollView([.horizontal]) { LazyVGrid(columns: columns, alignment: .leading, pinnedViews: [.sectionHeaders]) { // 固定表头区域 Section(header: headerView) { // 表格行 ForEach(teams) { team in Section(header: Text("") // 固定列占位 .frame(height: 40) .padding(.horizontal, 4)) { Text(team.city) .frame(height: 40) .padding(.horizontal, 4) .border(Color(.separator), width: 0.5) Text(team.name) .frame(height: 40) .padding(.horizontal, 4) .border(Color(.separator), width: 0.5) } .background(Color(.systemBackground)) } } } } LazyVGrid(columns: [columns[0]], alignment: .leading, pinnedViews: [.sectionHeaders]) { Section(header: Text("Team ID") .frame(width: 120, height: 40, alignment: .leading) .bold() .padding(.horizontal, 4) .background(Color(.systemGray5)) .border(Color(.separator), width: 0.5)) { ForEach(teams) { team in Text(String(team.teamId)) // 固定首列 .frame(width: 120, height: 40) .padding(.horizontal, 4) .background(Color(.systemGray6)) .border(Color(.separator), width: 0.5) } } } } } .border(Color(.separator), width: 1) } private var headerView: some View { HStack(spacing: 0) { Text("") .frame(width: 120, height: 40, alignment: .leading) .bold() .padding(.horizontal, 4) .background(Color(.systemGray5)) .border(Color(.separator), width: 0.5) Text("City") .frame(width: 150, height: 40, alignment: .leading) .bold() .padding(.horizontal, 4) .background(Color(.systemGray5)) .border(Color(.separator), width: 0.5) Text("Name") .frame(width: 200, height: 40, alignment: .leading) .bold() .padding(.horizontal, 4) .background(Color(.systemGray5)) .border(Color(.separator), width: 0.5) } .background(Color(.systemGray5)) } } #Preview { ScrollableTableView() }
内容的提问来源于stack exchange,提问作者cacjack12
相关产品推荐
相关产品推荐

