SwiftUI:动画问题-淡出而不是移动

3

我正在尝试构建一个自定义侧边栏菜单,当其中的按钮被点击时,它会产生动画效果。 为了调试目的,动画故意放慢到2.0秒。 如您所见,动画无法正常工作:

enter image description here

我怀疑这个问题有两个部分:

  1. 新选择的按钮的背景移出得比菜单快。 我认为这是根源于Button的默认系统动画。
  2. 当我用Text替换Button并使用.onTapGesture时,仍然会有淡入淡出的动画,因此我认为在设置FeatureButton中的selected时存在一些结构上的问题。

抱歉示例代码有点长,我尽量简化我的应用程序架构。 使用MenuState作为EnvironmentObject的原因是能够从应用程序的各个地方更改其属性。

下面是代码:

class MenuState: ObservableObject {
    @Published var currentFeature: Feature = .featureA
    @Published var menuOffset: CGFloat = 0
}

enum Feature: String, CaseIterable {
    case featureA = "Feature A"
    case featureB = "Feature B"
    case featureC = "Feature C"
}

extension Feature: Identifiable {
    var id: RawValue { rawValue }
}

struct ContentView: View {
    @StateObject var menuState = MenuState()

    var body: some View {
        ZStack(alignment: .leading) {
            content
            menu
        }
        .environmentObject(menuState)
        .animation(.easeOut(duration: 2.0), value: menuState.menuOffset)
    }

    var menu: some View {
        VStack {
            ForEach(Feature.allCases) { feature in
                FeatureButton(feature: feature)
            }
        }
        .frame(maxHeight: .infinity)
        .frame(width: 200)
        .background(.thinMaterial)
        .offset(x: menuState.menuOffset)
    }

    var content: some View {
        VStack {
            Button("Show Menu") {
                menuState.menuOffset = 0
            }
            Text(menuState.currentFeature.rawValue)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

struct FeatureButton: View {
    @EnvironmentObject var menuState: MenuState

    let feature: Feature
    var selected: Bool {
        return menuState.currentFeature == feature
    }

    var body: some View {
        Button(feature.rawValue) {
            menuState.currentFeature = feature
            menuState.menuOffset = -200
        }
        .buttonStyle(FeatureButtonStyle(selected: selected))
    }
}

struct FeatureButtonStyle: ButtonStyle {
    @EnvironmentObject var menuState: MenuState

    var selected: Bool
    public func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(maxWidth: .infinity, minHeight: 44)
            .foregroundColor(selected ? .blue : .primary)
            .background(Color.gray.opacity(selected ? 0.4 : 0))
            .contentShape(Rectangle())
    }
}

编辑: 由于某些原因,显式制作动画能够解决该问题,详见下面的答案。


所以,看起来你已经找到了解决问题的方法并可以将其发布为答案? - lazarevzubov
1个回答

1
问题可以通过将动画显式化而不是使用.animation修饰符来解决:
Button(feature.rawValue) {
    menuState.currentFeature = feature
        withAnimation(.easeOut) {
            menuState.menuOffset = -200
        }
    }
.buttonStyle(FeatureButtonStyle(selected: selected))

我不明白为什么它只能这样工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接