对导航栏标题下方的视图进行动画
我正在构建一个Toast消息。本质上它只是一个矩形视图,我想在当前屏幕的顶部、导航栏下方显示几秒钟。还有一个要求是这个动画要从顶部开始。到现在为止还算简单。
ToastView().transition(.move(edge: .top))
值得一提的是,我需要这个Toast的屏幕处于一个带有标题的导航视图(Navigation View)内部。当我将Toast放在视图中而不添加任何动画时,它就安放在导航栏下方,位置正合适。当我添加动画时,它会从屏幕顶部移动到正确的位置,但它会越过(也就是在导航栏之上)导航栏。
我希望得到完全相同的行为,但在Toast动画时,我希望它从导航栏下方进入(也就是从后方穿过)。
我的直觉是需要调整视图的z 索引,即确保NavBar的 z索引高于ToastView,但这并没有带来区别。欢迎给出任何建议。
解决方案
你需要将SwiftUI的 Toast视图放在导航栈内容之下,如下所示:
struct StackExample: View {
@State private var showToast = false
var body: some View {
NavigationStack {
ZStack(alignment: .top) {
// Main content
List {
Button {
withAnimation {
showToast.toggle()
}
if (showToast) {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
showToast = false
}
}
}
} label: {
Text("Item")
}
}
// Toast under NavBar
if showToast {
ToastView()
.padding(.top, 8)
.transition(.opacity.combined(with: .offset(y: -40)))
}
}
.navigationTitle("Stack Example")
}
}
}
备选方案
你可以尝试在主内容的背景中显示Toast视图。
你还提到:
还有一个要求是这个动画要从顶部开始。
过渡 .move(edge: .top) 的起始偏移量等于将要显示的内容的高度。如果你需要比这更大的移动,例如你希望从安全区域边界之外开始,只需通过增加内边距为内容提供更高的高度。
下面是一个示例,展示全部功能正常工作:
struct ContentView: View {
@State private var isShowing = false
var body: some View {
NavigationStack {
Text("Main content")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.navigationTitle("Title")
.background(alignment: .top) {
if isShowing {
toastView
.transition(.asymmetric(
insertion: .move(edge: .top),
removal: .opacity
))
}
}
.task {
try? await Task.sleep(for: .seconds(1))
withAnimation(.easeOut(duration: 3)) {
isShowing = true
} completion: {
withAnimation(.easeInOut.delay(3)) {
isShowing = false
}
}
}
}
}
private var toastView: some View {
RoundedRectangle(cornerRadius: 10)
.fill(.orange)
.padding(.horizontal)
.frame(maxWidth: .infinity)
.frame(height: 50)
.padding(.bottom, 250)
}
}

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。