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

SwiftUI:如何为ScrollView中的每个列表单元格单独应用MatchedGeometryEffect

解决方案

你当前把matchedGeometryEffect加在ForEach外层,所有单元格共用了同一个id: "shape",无法实现单个单元格的独立匹配效果,按下面步骤调整即可:

调整步骤

  • 将matchedGeometryEffect修饰符移动到ForEach循环内部的单个单元格根视图上
  • 给每个单元格设置唯一的匹配id,和当前循环的country绑定,确保同一个国家的常规样式、备选大尺寸样式使用完全相同的id和同一个命名空间
  • 切换showAlternate状态时用withAnimation包裹,触发过渡动画

修改后参考代码

struct ContentView: View {
    @Binding var countries: [Country]
    @State var showAlternate = false
    @Namespace var namespace

    var body: some View {
        NavigationView {
            ScrollView {
                // LazyVStack移到外层避免重复创建,优化性能
                LazyVStack {
                    ForEach(Array(countries.enumerated()), id: \.1.id) { (index,country) in
                        Group {
                            if !showAlternate {
                                // 原常规单元格样式
                                HStack {
                                    NavigationLink(
                                        destination: CountryView(country: country),
                                        label: {
                                            HStack {
                                                Image(country.image)
                                                    .resizable()
                                                    .scaledToFit()
                                                Text(country.display_name)
                                                    .foregroundColor(Color.black)
                                                    .padding(.leading)
                                                Spacer()
                                            }
                                            .padding(.top, 12.0)
                                            .frame(height: 80)
                                        }
                                    ).buttonStyle(FlatLinkStyle())                                   
                                }                            
                                .padding(.horizontal, 16.0)
                                .overlay(Divider(), alignment: .top)
                            } else {
                                // 后续实现的备选大尺寸样式,保持id和常规状态一致
                                HStack {
                                    // 大尺寸布局代码
                                }
                                .padding(.horizontal, 16.0)
                            }
                        }
                        .background(Rectangle().opacity(0.2)
                            // 每个单元格用和country绑定的唯一id
                            .matchedGeometryEffect(id: "country_bg_\(country.id)", in: namespace)
                        )
                    }
                }
            }
        }
        .font(Font.custom("Avenir", size: 22))
        // 切换状态示例,必须加动画包裹才会触发过渡效果
        .toolbar {
            Button("切换样式") {
                withAnimation {
                    showAlternate.toggle()
                }
            }
        }
    }
}

注意事项

  • 同一个元素的两种状态(常规/放大)必须使用完全相同的id和同一个namespace才能匹配成功
  • 几何匹配的两个视图层级尽量对应,避免出现异常形变效果

内容的提问来源于stack exchange,提问作者user17503091

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 13:15:03