【问题标题】:SwiftUI matchedGeometryEffect "Multiple inserted views in matched geometry group Pair warning" when View embedded in Button当视图嵌入在按钮中时,SwiftUI 匹配几何效果“匹配几何组中的多个插入视图对警告”
【发布时间】:2021-03-07 22:59:52
【问题描述】:

当用户选择不同的选项卡时,我想实现下划线从一个选项卡移动到另一个选项卡的幻灯片动画

我使用matchedGeometryEffect如下:

       HStack(spacing: 15) {
            ForEach(categories, id: \.self) { category in
                let isSelected = selectedVal == category
                Button {
                    withAnimation {
                        selectedVal = category
                    }
                } label: {
                    VStack(spacing: 4) {
                        Text(category)
                            .frame(width: 100)
                        if isSelected {
                            RoundedRectangle(cornerRadius: 5)
                                .frame(width: 50, height: 2)
                                .matchedGeometryEffect(id: "Category", in: animation, isSource: isSelected)
                        }
                    }
                }
            }
        }

这种方法适用于Multiple inserted views in matched geometry group Pair<String, ID>(first: "Category", second: SwiftUI.Namespace.ID(id: 10)) have isSource: true, results are undefined.的警告

当我从Button中提取RoundedRectangle时,警告消失了:

      HStack(spacing: 15) {
            ForEach(categories, id: \.self) { category in
                let isSelected = selectedVal == category
                VStack(spacing: 4) {
                    Button(category) {
                        withAnimation {
                            selectedVal = category
                        }
                    }
                    
                    if isSelected {
                        RoundedRectangle(cornerRadius: 5)
                            .frame(width: 50, height: 2)
                            .matchedGeometryEffect(id: "Category", in: animation, isSource: isSelected)
                    }
                }
            }
        }

我怀疑这与Button 未在第一个解决方案中的视图层次结构中删除有关,因此仍然持有对RoundedRectangle 的引用,这会使matchedGeometry 混淆,因为您不能拥有源视图“可见”,但我会认为 isSource 设置为选定状态会解决这个问题。有没有解释为什么我在第一种情况下收到警告?

【问题讨论】:

  • 对我来说它看起来像一个 SwiftUI 错误。
  • 我发现将动画持续时间设置为更快的时间有助于避免在补间期间用户可能在不合适的时间按下按钮的冲突。为什么它需要让程序崩溃而不是放弃,这超出了我的理解。

标签: ios swift animation swiftui


【解决方案1】:

问题是您可以一次仅在一个视图中设置具有相同命名空间的 matchedgeometryeffect。这样 SwiftUI 就可以确定要为哪个对象设置动画。这里是你设置几何效果所有三个具有相同命名空间的视图,所以 swiftUI 无法弄清楚如何为所有视图设置动画和布局。

struct ContentView: View {
    
    enum Tab: String {
        case one
        case two
        case three
    }
    
    @State private var selected: Tab = .one
    @Namespace private var tabNameSpace
    
    var body: some View {
        ZStack {
            HStack(spacing: 32) {
                
                ZStack {
                    if selected == .one {
                        Color.red
                            .frame(width: 100, height: 50)
                            .matchedGeometryEffect(id: "namespace", in: tabNameSpace)
                    }
                    
                    Text(Tab.one.rawValue)
                        .frame(width: 100, height: 50)
                        .onTapGesture {
                            withAnimation(.spring()) {
                                selected = .one
                            }
                        }
                }
                
                ZStack {
                    if selected == .two {
                        Color.red
                            .frame(width: 100, height: 50)
                            .matchedGeometryEffect(id: "namespace", in: tabNameSpace)
                    }
                    
                    Text(Tab.two.rawValue)
                        .frame(width: 100, height: 50)
                        .onTapGesture {
                            withAnimation(.spring()) {
                                selected = .two
                            }
                        }
                }
                
                ZStack {
                    if selected == .three {
                        Color.red
                            .frame(width: 100, height: 50)
                            .matchedGeometryEffect(id: "namespace", in: tabNameSpace)
                    }
                    
                    Text(Tab.three.rawValue)
                        .frame(width: 100, height: 50)
                        .onTapGesture {
                            withAnimation(.spring()) {
                                selected = .three
                            }
                        }
                }
                
            }
        }
    }
    
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 2022-06-14
    • 1970-01-01
    • 2015-06-05
    • 2021-12-08
    • 2020-07-15
    • 1970-01-01
    相关资源
    最近更新 更多