是否可以调整文本大小并匹配几何效果?

tim*_*tim 10 ios swift swiftui

我有一个使用匹配几何效果的叠加过渡,如本视频所示: 具有相同大小文本的匹配几何效果

我想在动画之后放大过渡的文本,但似乎文本框架没有及时缩放,导致文本在过渡时被缩短。 与不同大小的文本匹配的几何效果

有办法克服这个问题吗?

原文:

Text(info.name)
    .font(.system(size: 22, weight: .bold))
    .matchedGeometryEffect(id: info.name, in: namespace)
Run Code Online (Sandbox Code Playgroud)

转换后的文本:

Text(currentCard.name)
    .font(.title.bold())
    .matchedGeometryEffect(id: currentCard.name, in: namespace)
Run Code Online (Sandbox Code Playgroud)

谢谢

jos*_*ell 4

终于想通了!

在matchedGeometryEffect内动画字体大小

添加您在声明中@State var触发的单独字体大小。将其与 结合起来,字体大小就会变得很好!matchedGeometryEffectif.onAppearAnimatableCustomFontModifier

我知道。听起来很恶心。你不会相信这花了多长时间。这是一个工作示例。

struct ContentView: View {
    
    @Namespace var namespace
    @State var hero = false
    @State var heroFontLarge = false
    

    var body: some View {
        VStack {
            if hero {
                Text("hello")
                    .animatableFont(name: "San Francisco", size: heroFontLarge ? 64 : 16)
                    .matchedGeometryEffect(id: "title", in: namespace)
                    // Start the font size animation. Only gets called once the transition starts
                    .onAppear {
                        withAnimation(.linear(duration: 1)) {
                            heroFontLarge = true // Start animating a larger font
                        }
                    }
                    .transition(.scale(scale: 1)) // Stops a fading out bug
            } else {
                Text("hello")
                    .animatableFont(name: "San Francisco", size: heroFontLarge ? 64 : 16)
                    .matchedGeometryEffect(id: "title", in: namespace)
                    // Start the font size animation. Only gets called once the transition starts
                    .onAppear {
                        withAnimation(.linear(duration: 1)) {
                            heroFontLarge = false  // Start animating a smaller font
                        }
                    }
                    .transition(.scale(scale: 1)) // Stops a fading out bug
                
            }
            Button("Toggle") {
                withAnimation(.linear(duration: 1)) {
                    hero.toggle()
                }
            }
        }
    }
}



// A modifier that animates a font through various sizes.
// https://www.hackingwithswift.com/quick-start/swiftui/how-to-animate-the-size-of-text
struct AnimatableCustomFontModifier: ViewModifier, Animatable {
    var name: String
    var size: Double

    var animatableData: Double {
        get { size }
        set { size = newValue }
    }

    func body(content: Content) -> some View {
        content
            .font(.custom(name, size: size))
    }
}

// To make that easier to use, I recommend wrapping
// it in a `View` extension, like this:
extension View {
    func animatableFont(name: String, size: Double) -> some View {
        self.modifier(AnimatableCustomFontModifier(name: name, size: size))
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果您尝试在动画完成之前反转动画,则会出现一些问题。如果您可以延迟交互直到动画完成,那么应该不是问题。