ios - SwiftUI 像内置导航一样滑过动画
问题描述
我正在尝试复制 SwiftUI 的导航而不使用所有的黑盒魔法。但是,我在动画方面遇到了麻烦。直到第二次或第三次推送/弹出时才会发生动画。当它最终动画化时,很难描述它做了什么。但这绝对不是我所期望的。
我尝试了各种不同的动画,但通常是相同的行为。
struct RouterDemo: View {
@State private var items: [Int] = Array(0..<50)
@State private var selectedItem: Int?
var body: some View {
RouterStore(
route: $selectedItem,
state: { route in items.first(where: { $0 == route }) },
content: { ItemsList(items: items, selectedItem: $0) },
destination: { route, item in
ItemDetail(item: item, selectedItem: route)
}
)
}
}
public struct RouterStore<Destination, Content, Route, DestinationState>: View
where Destination: View,
Content: View,
Route: Hashable,
DestinationState: Equatable {
@Binding private var route: Route?
private let toDestinationState: (Route) -> DestinationState?
private let destination: (Binding<Route?>, DestinationState) -> Destination
private let content: (Binding<Route?>) -> Content
public init(
route: Binding<Route?>,
state toDestinationState: @escaping (Route) -> DestinationState?,
@ViewBuilder content: @escaping (Binding<Route?>) -> Content,
@ViewBuilder destination: @escaping (Binding<Route?>, DestinationState) -> Destination
) {
self._route = route
self.toDestinationState = toDestinationState
self.destination = destination
self.content = content
}
public var body: some View {
GeometryReader { geometry in
ZStack {
content($route)
wrappedDestination()
.frame(width: geometry.size.width)
.offset(
x: route == nil ? geometry.size.width : 0,
y: 0
)
.animation(self.animation)
}
}
}
private var animation: Animation = .easeIn(duration: 2)
@ViewBuilder
private func wrappedDestination() -> some View {
if let _route = Binding($route),
let _destinationState = toDestinationState(_route.wrappedValue) {
ZStack {
Group {
if #available(iOS 15.0, *) {
Color(uiColor: UIColor.systemBackground)
} else {
Color(UIColor.systemBackground)
}
}
.preferredColorScheme(.light)
.ignoresSafeArea()
self.destination($route, _destinationState)
}
} else {
EmptyView()
}
}
}
struct ItemsList: View {
let items: [Int]
@Binding var selectedItem: Int?
var body: some View {
List {
ForEach(items, id: \.self) { item in
Button(
action: { selectedItem = item },
label: { Text(String(item)) }
)
.contentShape(Rectangle())
}
}
}
}
struct ItemDetail: View {
let item: Int
@Binding var selectedItem: Int?
var body: some View {
VStack {
Text(String(item))
Button(
action: { selectedItem = nil },
label: { Text("Back") }
)
}
}
}
解决方案
感谢 Asperi 提供的链接,我明白了。
将动画应用到容器并为动画提供要监视的值来修复它。
推荐阅读
- katalon-studio - 我可以在邮件正文中添加一些 Katalon-Studio 控制台登录吗?
- python - 用于从 tkinter 中的按钮事件中弹出警报框的异常,无法找出问题的根源
- memory - Redis RSS 内存占用高
- javascript - 用于在 javascript 中查找动态字符串中字符的第二次出现的正则表达式
- c++ - 当 T 具有非平凡的析构函数时,类类型 T 的对象可以被常量初始化吗?
- reactjs - 没有浏览器支持录制视频
- sas - 如何对 Excel 文件中列出的数据集名称运行 Proc COMPARE
- objective-c - macOS 应用程序在 Mojave 中运行良好,但在 Catalina Beta 版中崩溃
- microsoft-teams - 在自适应卡片中单击操作按钮时选择消失
- php - 如何在php中删除多维数组的索引