【问题标题】:How to initialize a binding Bool value in a SwiftUI view如何在 SwiftUI 视图中初始化绑定 Bool 值
【发布时间】:2020-12-23 04:29:57
【问题描述】:

修订示例

根据我在下面的 cmets 中收到的 @pawello2222 的深思熟虑的回复,我修改了一个示例来展示我正在努力解决的问题。

为了演示我遇到的问题,我使用了父母和孩子的 2 个视图。在我的代码代码中,父视图执行多个步骤,但有时动画子视图在第一步中不可见。但是,当它确实变得可见时,动画已经呈现出最终状态的外观。您可以在以下示例中看到此行为。

父视图

struct ContentView: View {

@State var firstTime = true
@State var breath = false

var body: some View {
    VStack {
        
        //            This subview is not displayed until after the first time
        
        if !firstTime {
            SecondView(breath: $breath)
        }
        Spacer()
        
        //            A button click simulates the steps in my App by toggling the @Binding var
        Button("Breath") {
            withAnimation {
                self.breath.toggle()
                self.firstTime = false
            }
        }
        //            This vies shows what happens when the subview is being displayed with an intial state of false for the @Binding var
        Spacer()
        SecondView(breath: $breath)
    }
}

}

这是包含动画并使用@Binding var 控制动画外观的子视图。

struct SecondView: View {
@Binding var breath: Bool

var body: some View {
    Image(systemName: "flame")
        .resizable()
        .rotationEffect(.degrees(breath ? 360 : 0), anchor: .center)
        .scaleEffect(breath ? 1 : 0.2)
        .opacity(breath ? 1 : 0.75)
        .animation(.easeInOut(duration: 2))
        .foregroundColor(Color.red)
}

}

当您第一次执行此操作时,顶部子视图不会显示,并且当您单击按钮时,下部子视图会执行预期的动画,然后切换 firstTime 变量,以便顶部子视图可见。请注意,动画已完全展开,如果我要再进行另一个步骤(单击),@Binding 属性的值为 true,则视图根本不会改变。这是我正在努力解决的问题。如果第一步是切换 Bool 值的步骤,即使未显示子视图,我也希望使子视图不处于结束状态。换句话说,我只想在实际显示时初始化子视图,值为 true 以便动画总是从小开始。

这就是为什么我希望让子视图将 Binding var 初始化为 false,直到它第一次真正被调用(或将其状态重置为动画的缩小版本),以更可行的为准。

【问题讨论】:

  • 你会展示最少的可重现示例代码吗?否则,这只是一个猜测,如下所示,您很可能不会像您预期的那样得到答案。

标签: swiftui


【解决方案1】:

看起来你可能想用提供的参数初始化_breath

struct ContentView: View {
    @Binding var breath: Bool

    init(breath: Binding<Bool>) {
        _breath = breath
    }
}

但是,如果您想使用常量值(在您的示例中为 false),您可以这样做:

struct ContentView: View {
    @Binding var breath: Bool

    init(breath: Binding<Bool>) {
        _breath = .constant(false)
    }
}

但是,为什么需要breath: Binding&lt;Bool&gt; 参数呢?


编辑

这是一个如何使用@Binding 变量控制子视图动画的示例:

struct ContentView: View {
    @State var breath = false

    var body: some View {
        VStack {
            Button("Breath") {
                withAnimation {
                    self.breath.toggle()
                }
            }
            SecondView(breath: $breath)
        }
    }
}
struct SecondView: View {
    @Binding var breath: Bool

    var body: some View {
        Image(systemName: "flame")
            .imageScale(.large)
            .rotationEffect(.degrees(breath ? 360 : 0), anchor: .center)
            .scaleEffect(breath ? 1 : 0.2)
            .opacity(breath ? 1 : 0.75)
            .animation(.easeInOut(duration: 2))
    }
}

【讨论】:

  • 此视图包含一个动画,该动画需要以将 Breath 变量设置为 false 开始,然后当从其父视图调用视图时,Binding 变量将切换为 true,并且动画将按预期工作.如果我没有初始化为 false 并且父视图使用 true 值调用它,那么动画最终已经展开。所以我想强制变量以 false 值开始,然后将其切换为 true。
  • @lrreynolds 我建议你完全删除breath 变量并在子视图的.onAppear 中启动动画。
  • 我尝试在 .onappear() 中将值设置为 false 但这不起作用,因为值 true 是在执行 .onappear() 代码之前传入的,因此动画对于第一个周期。它正常工作是属性的初始值为 false,然后切换为 true。如果没有从需要切换此变量值的父级调用此视图,则可以使用 state 属性完成此操作。
  • @lrreynolds 我用一个简短的演示更新了我的答案,解释了如何在onAppear 中启动动画。
  • 我想我明白这一点,但父视图在视图出现后多次切换呼吸属性,所以如何在视图处于活动状态时为缩放效果修改器传递新值?
猜你喜欢
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多