ios - SwiftUI: matchedGeometryEffect and clipShape Animation Bug - Stack Overflow

Say I have a container view that I use to apply consistent styling to various contained views.struct F

Say I have a container view that I use to apply consistent styling to various contained views.

struct FormattedContainer<Content: View>: View {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
            content
                .padding()
                .background(Color.gray.opacity(0.2))
    }
}

I use it to enclose a couple of views that use matchedGeometryEffect to animate from one container to another.

struct ContentView: View {
    @Namespace var animation
    @State var isFlipped: Bool = false

    var body: some View {
        VStack {
            FormattedContainer {
                HStack {
                    Rectangle()
                    if isFlipped {
                        Text("This is the active container")
                            .layoutPriority(1)
                            .matchedGeometryEffect(id: "id", in: animation)
                    }
                }
            }
            Spacer(minLength: 40)
            FormattedContainer {
                HStack{
                    if !isFlipped {
                        Text("This is the active container")
                            .layoutPriority(1)
                            .matchedGeometryEffect(id: "id", in: animation)
                    }
                    Rectangle()
                }
            }
        }
        .contentShape(Rectangle())
        .padding()
        .onTapGesture {
            withAnimation {
                isFlipped.toggle()
            }
        }
    }
}

This works well and look like this:

If I add a clip shape to my container to give it rounded corners:

struct FormattedContainer<Content: View>: View {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
            content
                .padding()
                .background(Color.gray.opacity(0.2))
                .clipShape(RoundedRectangle(cornerRadius: 20)) <----- added line
    }
}

The animation disappears when moving from container to container:

Any ideas how to fix the formatted container so it has rounded corners and the animation doesn't disappear?

Say I have a container view that I use to apply consistent styling to various contained views.

struct FormattedContainer<Content: View>: View {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
            content
                .padding()
                .background(Color.gray.opacity(0.2))
    }
}

I use it to enclose a couple of views that use matchedGeometryEffect to animate from one container to another.

struct ContentView: View {
    @Namespace var animation
    @State var isFlipped: Bool = false

    var body: some View {
        VStack {
            FormattedContainer {
                HStack {
                    Rectangle()
                    if isFlipped {
                        Text("This is the active container")
                            .layoutPriority(1)
                            .matchedGeometryEffect(id: "id", in: animation)
                    }
                }
            }
            Spacer(minLength: 40)
            FormattedContainer {
                HStack{
                    if !isFlipped {
                        Text("This is the active container")
                            .layoutPriority(1)
                            .matchedGeometryEffect(id: "id", in: animation)
                    }
                    Rectangle()
                }
            }
        }
        .contentShape(Rectangle())
        .padding()
        .onTapGesture {
            withAnimation {
                isFlipped.toggle()
            }
        }
    }
}

This works well and look like this:

If I add a clip shape to my container to give it rounded corners:

struct FormattedContainer<Content: View>: View {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
            content
                .padding()
                .background(Color.gray.opacity(0.2))
                .clipShape(RoundedRectangle(cornerRadius: 20)) <----- added line
    }
}

The animation disappears when moving from container to container:

Any ideas how to fix the formatted container so it has rounded corners and the animation doesn't disappear?

Share Improve this question asked Mar 27 at 2:50 colbrewcolbrew 1011 silver badge9 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

You should not clip content. You can add an in: parameter to specify what shape the background should be in:

.background(Color.gray.opacity(0.2), in: .rect(cornerRadius: 20))
// remove clipShape!

If you do need clipShape to clip other content, you need to use a third Text on top of everything to match the geometry of one of the other Texts.

VStack {
    FormattedContainer {
        HStack {
            Rectangle()
            if isFlipped {
                Text("This is the active container")
                    .hidden()
                    .layoutPriority(1)
                    .matchedGeometryEffect(id: true, in: animation)
            }
        }
    }
    Spacer(minLength: 40)
    FormattedContainer {
        HStack{
            if !isFlipped {
                Text("This is the active container")
                    .hidden()
                    .layoutPriority(1)
                    .matchedGeometryEffect(id: false, in: animation)
            }
            Rectangle()
        }
    }
}
.contentShape(Rectangle())
.padding()
.onTapGesture {
    withAnimation {
        isFlipped.toggle()
    }
}
.overlay {
    // this is the only Text you see!
    // it matches the geometry of either the top container's or bottom container's text depending on isFlipped
    Text("This is the active container")
        .matchedGeometryEffect(id: isFlipped, in: animation, isSource: false)
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744115210a4559140.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信