我正在尝试构建一个自定义侧边栏菜单,当其中的按钮被点击时,它会产生动画效果。 为了调试目的,动画故意放慢到2.0秒。 如您所见,动画无法正常工作:
我怀疑这个问题有两个部分:
- 新选择的按钮的背景移出得比菜单快。 我认为这是根源于
Button
的默认系统动画。 - 当我用
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())
}
}
编辑: 由于某些原因,显式制作动画能够解决该问题,详见下面的答案。