我在选择按钮时遇到问题。我使用枚举来跟踪应用程序中的页面及其值,例如页面标题和页面图标。我使用这些值在 VStack 内创建一个带有按钮的菜单。我使用 ForEach 检索所有枚举值 (AppScreen) 并将它们填充到按钮的标签中。到目前为止,一切都很好,但是当我选择一个按钮时,图标动画也会影响之前选择的按钮。让我举个例子:
我的按钮的标题是“按钮 1”和“按钮 2”及其相关图标。当我选择“按钮 1”时,图标动画工作正常,但当我选择“按钮 2”时,它无法正常工作,因为它为“按钮 1”和“按钮 2”的图标设置动画,而不仅仅是“按钮” 2.”
我哪里出错了?
这是我的代码:
import Foundation
enum AppScreen: CaseIterable, Identifiable {
case btn1, btn2
var id: AppScreen { self }
var screenName: String {
switch self {
case .btn1: "btn1"
case .btn2: "btn2"
}
}
var screenIcon: String {
switch self {
case .btn1: "exclamationmark.arrow.triangle.2.circlepath"
case .btn2: "person.2"
}
}
}
struct AppSideBar: View {
@Binding var appScreen: AppScreen?
@State private var selection: String = ""
var body: some View {
HStack {
VStack {
ForEach(AppScreen.allCases) { screen in
Button {
selection = screen.screenName
} label: {
VStack {
Image(systemName: screen.screenIcon)
Text(screen.screenName)
.foregroundStyle(selection == screen.screenName ? .red : .white)
}
}
.symbolEffect(.bounce, value: selection == screen.screenName)
.buttonStyle(.borderless)
}
}
}
#if os(macOS)
.frame(width: NSScreen.main!.visibleFrame.width / 1.6,
height: NSScreen.main!.visibleFrame.height - 100)
#endif
}
}
文档指出“每次值更改时都会触发动画”。所以当条件从 false 变为 true 时会触发,但从 true 变为 false 时也会触发。
要解决此问题,我认为您需要为每个按钮设置单独的标志,并且标志仅应在应用选择时更改,而不是在选择移开时更改。像这样:
@State private var selectionApplied = [AppScreen: Bool]()
ForEach(AppScreen.allCases) { screen in
Button {
let wasApplied = selectionApplied[screen] ?? false
selectionApplied[screen] = !wasApplied
selection = screen.screenName
} label: {
// as before
}
.symbolEffect(.bounce, value: selectionApplied[screen] ?? false)
.buttonStyle(.borderless)
}