代码之家  ›  专栏  ›  技术社区  ›  Z S

使用matchedGeometryEffect为边框创建“滑动”效果

  •  0
  • Z S  · 技术社区  · 2 年前

    @objc public enum ContactTabStyle: Int, CaseIterable {
        case one, two, three, four
        
        public var segmentTitle: String {
            switch self {
                case .one: return "Hello"
                case .two: return "World"
                case .three: return "Three"
                case .four: return "Four"
            }
        }
    }
    
    struct SwiftUIView: View {
        let segments: [ContactTabStyle] = [.one, .two, .three, .four]
        @State var selectedTab: ContactTabStyle = .one
        
        @Namespace var tabName
        
        var body: some View {
            HStack {
                ForEach(segments, id: \.self) { segment in
                    Button {
                        selectedTab = segment
                    } label: {
                        Text(segment.segmentTitle)
                            .padding(12.0)
                            .border(selectedTab == segment ? Color.blue : Color.clear, width: 3.0)
                            .cornerRadius(4.0)
                            .matchedGeometryEffect(id: segment.segmentTitle, in: tabName) // doesn't work
                    }
                }
            }
        }
    }
    

    视图看起来和工作都很好,但我无法将动画从一个选择“滑动”到另一个选择。它只是做一个正常的SwiftUI淡入淡出。我认为我应该使用 matchedGeometryEffect 以获得滑动效果,但似乎不起作用。我已尝试添加 匹配的几何效果 按钮周围的标签也一样,但它也不起作用。

    以下是它的预览:

    enter image description here

    2 回复  |  直到 2 年前
        1
  •  1
  •   Sweeper    2 年前

    这个 Text s不需要匹配几何图形,而是 边界 需要匹配几何图形。

    如果您使用 border 要制作边框,边框不是其自己的“视图”,因此不能修改 只有 与的边界 matchedGeometryEffect 。一种解决方法是将边界添加为 background 文本 或者 Button (这些效果略有不同——看看你更喜欢哪一种)。

    Button {
        selectedTab = segment
    } label: {
        Text(segment.segmentTitle)
            .padding(12.0)
            .background {
                if selectedTab == segment {
                    RoundedRectangle(cornerRadius: 4)
                        .stroke(lineWidth: 3)
                        // every border should have the same id!
                        .matchedGeometryEffect(id: "selection", in: tabName)
                }
            }
            
    }
    

    Button {
        selectedTab = segment
    } label: {
        Text(segment.segmentTitle)
            .padding(12.0)
            
    }
    .background {
        if selectedTab == segment {
            RoundedRectangle(cornerRadius: 4)
                .stroke(Color.accentColor, style: .init(lineWidth: 3))
                .matchedGeometryEffect(id: "selection", in: tabName)
        }
    }
    .animation(.default, value: selectedTab)
    
        2
  •  0
  •   ttarchala    2 年前

    matchedGeometryEffect() 用于更改单个元素的位置。在这里,你要改变的是4种不同元素的颜色。

    我认为你必须将你的盒子定义为 View (或 Shape 等),其位置在某种程度上取决于 selectedTab 。然后应该正确设置动画。

    推荐文章