卡片间距异常:点击卡片时上下间距增大
问题:点击卡片时卡片上下间距异常增大
现象描述
- 点击卡片后,卡片的上下间距会逐步增大,对应三种状态:
- 初始未点击的卡片布局
- 点击一次翻面后的布局
- 点击两次匹配后的布局
相关代码
CardView
struct CardView: View { // String -> MemoryGame<String>.Card let card: MemoryGame<String>.Card var body: some View { ZStack { let shape = RoundedRectangle(cornerRadius: 20.0) if card.isFaceUp { shape.fill(.white) shape.strokeBorder(lineWidth: 3) Text(card.content) // 我认为问题根源可能在这里 .font(.largeTitle) } else if card.isMatched { shape.opacity(0.0) } else { shape.fill() } } } }
ContentView
struct ContentView: View { @ObservedObject var viewModel: EmojiMemoryGame var body: some View { VStack { Text("Memorize!") .font(.largeTitle) Group { Text(viewModel.themeName) .font(.subheadline) ScrollView { LazyVGrid(columns: [GridItem(.adaptive(minimum: 75))]) { ForEach(viewModel.cards) { card in CardView(card: card) .aspectRatio(2/3, contentMode: .fit) .onTapGesture { viewModel.choose(card) } } } } } .foregroundColor(viewModel.theme.uiColor) .padding(.horizontal) // Spacer() Button { viewModel.startNewGame() } label: { Text("New Game") .font(.title) } Text("Score: \(viewModel.score)") } } }
问题分析
你的定位完全正确——卡片在不同状态下的内在尺寸不一致。当卡片翻面显示Text时,Text的存在会让ZStack的内在尺寸产生微小变化,而LazyVGrid会根据子视图的实时尺寸重新计算网格间距,最终导致间距跳动。
解决方案
让CardView在所有状态下保持固定尺寸,就能彻底解决这个问题,有两种常用实现方式:
方式一:给CardView添加固定尺寸约束
把aspectRatio从父视图移到CardView内部的ZStack上,确保无论卡片状态如何,尺寸都保持一致:
struct CardView: View { let card: MemoryGame<String>.Card var body: some View { ZStack { let shape = RoundedRectangle(cornerRadius: 20.0) if card.isFaceUp { shape.fill(.white) shape.strokeBorder(lineWidth: 3) Text(card.content) .font(.largeTitle) } else if card.isMatched { shape.opacity(0.0) } else { shape.fill() } } .aspectRatio(2/3, contentMode: .fit) // 固定尺寸比例 } }
方式二:始终保留Text组件(仅隐藏而非移除)
让Text始终存在于布局中,只是在非正面状态下设置透明度为0,这样布局结构完全一致,不会产生尺寸变化:
struct CardView: View { let card: MemoryGame<String>.Card var body: some View { ZStack { let shape = RoundedRectangle(cornerRadius: 20.0) // 处理卡片背景状态 if card.isFaceUp { shape.fill(.white) shape.strokeBorder(lineWidth: 3) } else if card.isMatched { shape.opacity(0.0) } else { shape.fill() } // 始终保留Text,仅在非正面状态隐藏 Text(card.content) .font(.largeTitle) .opacity(card.isFaceUp ? 1.0 : 0.0) } } }
两种方式都能解决间距跳动问题,你可以根据自己的代码习惯选择。
内容的提问来源于stack exchange,提问作者cs-moushuai
相关产品推荐
相关产品推荐

