And*_*omb 7 navigation swiftui ios-navigationview swiftui-navigationlink
我正在尝试按顺序获得一个深层嵌套的编程导航堆栈。当手动完成导航(即:按下链接)时,以下代码按预期工作。当您按下Set Nav
按钮时,导航堆栈确实发生了变化 - 但不像预期的那样 - 最终堆栈损坏[start -> b -> bbb]
,并且视图之间有很多翻转
class NavState: ObservableObject {
@Published var firstLevel: String? = nil
@Published var secondLevel: String? = nil
@Published var thirdLevel: String? = nil
}
struct LandingPageView: View {
@ObservedObject var navigationState: NavState
func resetNav() {
self.navigationState.firstLevel = "b"
self.navigationState.secondLevel = "ba"
self.navigationState.thirdLevel = "bbb"
}
var body: some View {
return NavigationView {
List {
NavigationLink(
destination: Place(
text: "a",
childValues: [ ("aa", [ "aaa"]) ],
navigationState: self.navigationState
).navigationBarTitle("a"),
tag: "a",
selection: self.$navigationState.firstLevel
) {
Text("a")
}
NavigationLink(
destination: Place(
text: "b",
childValues: [ ("bb", [ "bbb"]), ("ba", [ "baa", "bbb" ]) ],
navigationState: self.navigationState
).navigationBarTitle("b"),
tag: "b",
selection: self.$navigationState.firstLevel
) {
Text("b")
}
Button(action: self.resetNav) {
Text("Set Nav")
}
}
.navigationBarTitle("Start")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct Place: View {
var text: String
var childValues: [ (String, [String]) ]
@ObservedObject var navigationState: NavState
var body: some View {
List(childValues, id: \.self.0) { childValue in
NavigationLink(
destination: NextPlace(
text: childValue.0,
childValues: childValue.1,
navigationState: self.navigationState
).navigationBarTitle(childValue.0),
tag: childValue.0,
selection: self.$navigationState.secondLevel
) {
Text(childValue.0)
}
}
}
}
struct NextPlace: View {
var text: String
var childValues: [String]
@ObservedObject var navigationState: NavState
var body: some View {
List(childValues, id: \.self) { childValue in
NavigationLink(
destination: FinalPlace(
text: childValue,
navigationState: self.navigationState
).navigationBarTitle(childValue),
tag: childValue,
selection: self.$navigationState.thirdLevel
) {
Text(childValue)
}
}
}
}
struct FinalPlace: View {
var text: String
@ObservedObject var navigationState: NavState
var body: some View {
let concat: String = "\(navigationState.firstLevel)/\(navigationState.secondLevel))/\(navigationState.thirdLevel)/"
return VStack {
Text(text)
Text(concat)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我最初试图将导航转换动画作为问题源来解决 - 但如何禁用 NavigationView 推送和弹出动画表明这是不可配置的
是否有任何关于 >1 级程序化导航的合理示例?
编辑:我希望在这里获得的部分内容也是导航正常工作的初始状态- 如果我从具有导航状态的外部上下文进入我希望反映(即:从具有一些应用程序内上下文的通知开始从,或从保存到磁盘编码状态)然后我希望能够加载顶部View
导航正确指向正确的子视图。本质上 -用实际值替换 the 中的nil
s NavState
。Qt 的 QML 和 ReactRouter 都可以声明性地做到这一点——SwiftUI 也应该能够做到。
现在我们有了NavigationStack
动态异构路径支持。因此更新的方法可能如下。
注意:虽然现在可以大大简化原始版本:a)我想保留视图层次结构b)我想展示不同模型类型的处理
使用 Xcode 14 / iOS 16 进行测试
struct LandingPageView2: View {
class NavState: ObservableObject {
@Published var path = NavigationPath()
let level1 = [
"a" : ["bb", "ba"],
"b" : ["bb", "ba"]
]
let level2 = [
"bb" : ["baa", "bbb"],
"ba" : ["baa", "bbb"]
]
}
struct Lev1: Hashable {
var text: String
}
struct Lev2: Hashable {
var text: String
}
struct Lev3: Hashable {
var text: String
}
func resetNav() {
self.navigationState.path.append(Lev1(text: "b"))
self.navigationState.path.append(Lev2(text: "ba"))
self.navigationState.path.append(Lev3(text: "bbb"))
}
@ObservedObject var navigationState: NavState
var body: some View {
NavigationStack(path: $navigationState.path) {
List {
NavigationLink("a", value: Lev1(text: "a"))
NavigationLink("b", value: Lev1(text: "b"))
Button(action: self.resetNav) {
Text("Set Nav")
}
}
.navigationDestination(for: Lev1.self) {
Place(text: $0.text, childValues: navigationState.level1[$0.text] ?? [])
}
.navigationDestination(for: Lev2.self) {
NextPlace(text: $0.text, childValues: navigationState.level2[$0.text] ?? [])
}
.navigationDestination(for: Lev3.self) {
FinalPlace(text: $0.text)
}
.navigationBarTitle("Start")
}
.navigationViewStyle(StackNavigationViewStyle())
.environmentObject(navigationState)
}
// MARK: -
struct Place: View {
var text: String
var childValues: [String]
var body: some View {
List(childValues, id: \.self) {
NavigationLink($0, value: Lev2(text: $0))
}
.navigationTitle(text)
}
}
struct NextPlace: View {
var text: String
var childValues: [String]
var body: some View {
List(childValues, id: \.self) {
NavigationLink($0, value: Lev3(text: $0))
}
.navigationTitle(text)
}
}
struct FinalPlace: View {
var text: String
@EnvironmentObject var navigationState: NavState
var body: some View {
VStack {
Text(text)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为动画完成时会形成新的堆栈级别,这就是它在手动点击的情况下起作用的原因。
通过以下修改,它可以工作:
func resetNav() {
self.navigationState.firstLevel = "b"
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.navigationState.secondLevel = "ba"
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.navigationState.thirdLevel = "bbb"
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1533 次 |
最近记录: |