在SwiftUI中,此代码用于切换视图的显示:
@State var show = true
Button { withAnimation { show.toggle() }}
label: { Image(systemName: show ? "chevron.down" : "chevron.right") }
if show { ... }
如果show是@State变量,则会显示动画。
然而,我发现如果show更改为@AppStorage(因此保持show状态(,动画将不会显示。
有没有办法既能保持演出状态,又能保持动画?
您还可以将withAnimation {}
替换为.animation(<#T##animation: Animation?##Animation?#>, value: <#T##Equatable#>)
修饰符,然后它似乎可以直接使用@AppStorage包装的变量。
import SwiftUI
struct ContentView: View {
@AppStorage("show") var show: Bool = true
var body: some View {
VStack {
Button {
self.show.toggle()
}
label: {
Rectangle()
.fill(Color.red)
.frame(width: self.show ? 200 : 400, height: 200)
.animation(.easeIn, value: self.show)
}
Rectangle()
.fill(Color.red)
.frame(width: self.show ? 200 : 400, height: 200)
.animation(.easeIn, value: self.show)
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
编辑:在评论之后,另一个解决方案
import SwiftUI
struct ContentView: View {
@State private var show: Bool
init() {
self.show = UserDefaults.standard.bool(forKey: "show")
// Or self._show = State(initialValue: UserDefaults.standard.bool(forKey: "show"))
}
var body: some View {
VStack {
Button {
withAnimation {
self.show.toggle()
}
}
label: {
Text("Toggle")
}
if show {
Rectangle()
.fill(Color.red)
.frame(width: 200 , height: 200)
}
}
.padding()
.onChange(of: self.show) { newValue in
UserDefaults.standard.set(newValue, forKey: "show")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
尝试将代码移动到视图模型中,使属性不在同一视图中。这样的东西应该可以解决动画问题:
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView().environmentObject(ViewModel()) }
}
}
final class ViewModel: ObservableObject {
@AppStorage("show") var show = true
}
struct ContentView: View {
@EnvironmentObject var viewModel: ViewModel
var body: some View {
VStack {
Button {
withAnimation { viewModel.show.toggle() }
} label: {
Image(systemName: "chevron.right")
.rotationEffect(Angle(degrees: viewModel.show ? 0 : 90))
}
if viewModel.show { /* ... */ }
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}