SwiftUI实现卡片全屏展开并禁用ScrollView滚动的技术需求
解决方案:实现SwiftUI可展开全屏卡片并控制ScrollView滚动
要实现你需要的效果,核心是把卡片的展开状态提升到父视图统一管理,这样才能控制其他卡片的显示、ScrollView的滚动状态,同时通过GeometryReader获取屏幕尺寸来实现全屏卡片。以下是修改后的完整代码:
修改后的DisciplineView
import SwiftUI struct DisciplineView: View { // 跟踪当前展开的卡片标题,nil表示无卡片展开 @State private var expandedCard: String? var body: some View { GeometryReader { geometry in ScrollView(showsIndicators: false) { LazyVStack { // 根据展开状态决定显示内容 if let expandedTitle = expandedCard { // 只显示展开的卡片,并设置高度为屏幕高度 Card(cardTitle: expandedTitle, isExpanded: true) { withAnimation { expandedCard = nil } } .frame(height: geometry.size.height) } else { // 无卡片展开时显示全部卡片 Card(cardTitle: "Notes", isExpanded: false) { withAnimation { expandedCard = "Notes" } } Card(cardTitle: "Planner", isExpanded: false) { withAnimation { expandedCard = "Planner" } } Card(cardTitle: "Homeworks / Exams", isExpanded: false) { withAnimation { expandedCard = "Homeworks / Exams" } } } } .ignoresSafeArea() } // 有卡片展开时禁用ScrollView滚动 .disabled(expandedCard != nil) } } } struct DisciplineView_Previews: PreviewProvider { static var previews: some View { DisciplineView() } }
修改后的Card组件
import SwiftUI struct Card: View { let cardTitle: String let isExpanded: Bool let onTap: () -> Void var body: some View { RoundedRectangle(cornerRadius: 30, style: .continuous) .stroke(style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round)) .foregroundColor(.gray.opacity(0.2)) .frame(width: .infinity, height: isExpanded ? nil : 50) .background( VStack { cardInfo if isExpanded { Spacer() } } .padding(isExpanded ? 10 : 0) ) // 展开时添加深色背景,配合白色文字提升可读性 .background(isExpanded ? Color.black : Color.white) } var cardInfo: some View { HStack { Text(cardTitle) .font(.title).bold() .foregroundColor(isExpanded ? .white : .black) .padding(.leading, 10) Spacer() Image(systemName: isExpanded ? "arrowtriangle.up.square.fill" : "arrowtriangle.down.square.fill") .padding(.trailing, 10) .onTapGesture(perform: onTap) } } } struct Card_Previews: PreviewProvider { static var previews: some View { Card(cardTitle: "Test", isExpanded: false, onTap: {}) } }
关键修改说明
- 状态统一管理:将卡片的展开状态从Card内部移到父视图
DisciplineView,通过expandedCard变量跟踪当前展开的卡片,实现隐藏其他卡片的逻辑。 - 全屏卡片实现:利用
GeometryReader获取屏幕高度,给展开的卡片设置对应高度,确保占满整个屏幕。 - 禁用ScrollView滚动:通过
.disabled(expandedCard != nil),在有卡片展开时直接禁用ScrollView的交互,停止滚动。 - 组件解耦:Card组件只负责展示逻辑,点击和状态由父视图控制,符合SwiftUI单向数据流的设计思路。
内容的提问来源于stack exchange,提问作者Rares
相关产品推荐
相关产品推荐

