SwiftUI:将动画添加到 Picker 而不将其添加到值

SwiftUI: Add animation to Picker without adding it to the values

我正在尝试根据切换为选择器的 hiding/showing 设置动画。如果是真还是假,我希望选择器 easeInOut.

我试过将 .animation(Animation.easeInOut(duration: 0.5)) 添加到选择器本身或选择器所在的 HStack,但两者都将动画添加到选择器内的值,并且在滚动值时应用程序崩溃。

        HStack {
            if showPicker {
                Picker(selection: $selected.value, label: Text(selected.type)) {
                    ForEach(digits, id: \.self) { d in
                        Text("\(d)")
                    }
                }
                .frame(width: 40)
            }
        }
        .animation(Animation.easeInOut(duration: 2))

            if showPicker {
                Picker(selection: $selected.value, label: Text(selected.type)) {
                    ForEach(digits, id: \.self) { d in
                        Text("\(d)")
                    }
                }
                .frame(width: 40)
                .animation(Animation.easeInOut(duration: 0.5))
            }

这两个选项都会为选择器 hiding/showing 设置动画,但它也会为滚动选择器中的值设置动画,这会导致它崩溃。

如有任何帮助,我们将不胜感激。

谢谢

关于您的第一种方法,将动画放在 HStack 上。永远不要那样做。根据声明文件中的注释:

Use this modifier on leaf views rather than container views. The animation applies to all child views within this view; calling animation(_:) on a container view can lead to unbounded scope.

我试过你的第二种方法(从你的 post 中填充缺失的位),它不会崩溃。也许你可以用一个完全可重现的例子来更新你的问题。

将动画更改为显式,因此其他参数不受影响:

struct PickerWhosebug: View {
    @State private var showPicker = true
    @State private var value: Int = 1

    let digits: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

    var body: some View {
        VStack {
            Text("Selected \(value)")

            HStack {
                if showPicker {
                    Picker(selection: $value, label: Text("Label")) {
                        ForEach(digits, id: \.self) { d in
                            Text("\(d)")
                        }
                    }
                    .frame(width: 40)
                }
            }


            Button("Tap Me") {
                withAnimation(Animation.easeInOut(duration: 2)) {
                    self.showPicker.toggle()
                }

            }
        }

    }
}