You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

卡片间距异常:点击卡片时上下间距增大

问题:点击卡片时卡片上下间距异常增大

现象描述

  • 点击卡片后,卡片的上下间距会逐步增大,对应三种状态:
    • 初始未点击的卡片布局
    • 点击一次翻面后的布局
    • 点击两次匹配后的布局

相关代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:35:35