如何在转换时忽略父视图的转换

问题描述 投票:0回答:1

我有一个有条件地显示按钮的组件视图。我希望这个按钮在出现/消失时有动画效果。

.transition(.move(edge: .trailing))
做我想做的事。

但是,如果组件的父组件移动,子组件的动画将相对于全局帧运行,而不是相对于其父组件的帧运行。

我相信应该有一种方法来改变这种行为。组件的实现不应该取决于它的使用方式。

The animation while using Component

我有另一种方法来实现我想要的,但它不是过渡动画。它手动修改偏移量。但是,我相信应该有一个使用转换的解决方案。组件的子组件可能需要出现/消失生命周期用于其他目的。

The animation while using ComponentAlternative

import SwiftUI
import PlaygroundSupport

struct Component: View {
    let state: Bool
    
    var body: some View {
        HStack() {
            Text("Placeholder")
                .padding()
            Spacer()
            if (state) {
                Color.red
                    .frame(width: 20, height: 20)
                    .padding()
                    .transition(.move(edge: .trailing))
                
            }
        }
        .frame(width: 200, height: 200)
        .background(Color.blue)
        .clipped()
    }
}

struct ComponentAlternative: View {
    let state: Bool
    
    var body: some View {
        HStack() {
            Text("Placeholder")
                .padding()
            Spacer()
            Color.red
                .frame(width: 20, height: 20)
                .padding()
                .transition(.move(edge: .trailing))
                .offset(x: state ? 0 : 50)
        }
        .frame(width: 200, height: 200)
        .background(Color.blue)
        .clipped()
    }
}

struct DemoView: View {
    @State private var state: Bool = false
    
    var body: some View {
        ZStack {
            Toggle(isOn: $state, label: {})
            
            Component(state: state)
                .frame(width: 200, height: 200)
                .background(Color.blue)
                .clipped()
                .padding(.top, state ? 200  : 0)
        }
        .frame(width: 400, height: 400)
        .animation(.default.speed(0.1), value: state)
    }
}

PlaygroundPage.current.setLiveView(DemoView())
swiftui
1个回答
0
投票

这就是

geometryGroup
的用途。将其添加到
ComponentView
,但在
.padding(.top, state ? 200 : 0)
之前。

Component(state: state)
    .geometryGroup() // <-----
    .frame(width: 200, height: 200)
    .background(Color.blue)
    .clipped()
    .padding(.top, state ? 200  : 0)

这基本上可以防止填充动画直接影响

Component
。父级为其填充设置动画,而
Color.red
则为过渡设置动画,所有这些都是单独进行的。

© www.soinside.com 2019 - 2024. All rights reserved.