我之前问过这个问题,但我知道我已经把它提炼成了一块可以在操场上运行的示例代码。
问题的基础是,我有两个视图被父视图切换。内容视图和设置视图。内容视图有三个标签,第三个标签的框架设置为与其他两个标签的最宽尺寸相匹配。
在我将动画添加到在“内容”视图和“设置”视图之间切换的视图之前,这一切都很正常。但当我添加动画时,它会“级联”到内容视图中,导致3标签在屏幕上飞过,而不仅仅是正确对齐。
下面是示例代码,如果你想玩它,可以将其剪切并粘贴到操场上。
import PlaygroundSupport
import SwiftUI
// Preference key which tracks the largest with of a label.
struct LabelWidthPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = max(value, nextValue())
}
}
// View modifier for tracking the size of a label.
struct LabelWidthObserver: ViewModifier {
func body(content: Content) -> some View {
content.background {
GeometryReader { geometry in
Color.clear.preference(key: LabelWidthPreferenceKey.self, value: geometry.size.width)
}
}
}
}
struct RootView: View {
@State private var showSettings = false
var body: some View {
Group {
if showSettings {
SettingsView { showSettings.toggle() }
} else {
ContentView { showSettings.toggle() }
}
}
.animation(.easeInOut, value: showSettings)
}
}
struct SettingsView: View {
let toggleSettings: () -> Void
var body: some View {
Text("Here be settings")
Button("Cancel") { toggleSettings() }
}
}
struct ContentView: View {
let toggleSettings: () -> Void
@State private var labelWidth: CGFloat = 20.0
var body: some View {
VStack(alignment: .leading, spacing: 4.0) {
Text("Line 1").modifier(LabelWidthObserver()).border(.red)
Text("longer line two").modifier(LabelWidthObserver()).border(.red)
Text("Line 3")
.frame(minWidth: labelWidth, alignment: .trailing)
.border(.green)
Button("Show settings") { toggleSettings() }
}
.onPreferenceChange(LabelWidthPreferenceKey.self) {
labelWidth = max(labelWidth, $0)
}
}
}
PlaygroundPage.current.setLiveView(RootView())
有人知道如何在不触发第三个标签动画的情况下,为两个视图之间的过渡设置动画吗?