swift - 如何在 SwiftUI 中使用 NavigationView 创建自定义 TabView?
问题描述
[编辑] - 这个问题已经过编辑和简化。
我需要创建一个 CustomLooking TabView 而不是默认的。
这是我解决问题的完整代码。只需运行下面的代码。
import SwiftUI
enum TabName {
case explore, network
}
struct ContentView: View {
@State var displayedTab: TabName = .explore
var body: some View {
VStack(spacing: 0) {
Spacer()
switch displayedTab {
case .explore: AViewWhichNavigates(title: "Explore").background(Color.yellow)
case .network: AViewWhichNavigates(title: "Network").background(Color.green)
}
Spacer()
CustomTabView(displayedTab: $displayedTab)
}
}
}
struct CustomTabView: View {
@Binding var displayedTab: TabName
var body: some View {
HStack {
Spacer()
Text("Explore").border(Color.black, width: 1).onTapGesture { self.displayedTab = .explore }
Spacer()
Text("Network").border(Color.black, width: 1).onTapGesture { self.displayedTab = .network }
Spacer()
}
}
}
struct AViewWhichNavigates: View {
let title: String
var body: some View {
NavigationView(content: {
NavigationLink(destination: Text("We are one level deep in navigation")) {
Text("You are at root. Tap to navigate").navigationTitle(title)
}
})
}
}
在 tab#1 上单击导航。切换到标签#2,然后切换回标签#1。您将看到 tab#1 已弹出到根目录。
每次切换标签时,如何防止 customTabView 弹出到根目录?
解决方案
问题是未记录 Navigation isActive 状态以及显示的选项卡状态。
通过记录每个选项卡的导航状态以及哪个选项卡处于活动状态,可以为每个选项卡显示正确的导航状态。
可以改进模型以删除元组并使其更灵活,但关键是使用 getter 和 setter 来使用每个选项卡的导航状态的封装模型,以便允许 NavigationLink 通过捆绑。
我已经简化了顶层 VStack 并删除了顶层开关,因为这里不需要它,但可以添加回来以便在实际实现中在顶层使用不同类型的视图
enum TabName : String {
case Explore, Network
}
struct ContentView: View {
@State var model = TabModel()
init(){
UINavigationBar.setAnimationsEnabled(false)
}
var body: some View {
VStack(spacing: 0) {
Spacer()
AViewWhichNavigates(model: $model).background(Color.green)
Spacer()
CustomTabView(model:$model)
}
}
}
struct CustomTabView: View {
@Binding var model: TabModel
var body: some View {
HStack {
Spacer()
Text("Explore").border(Color.black, width: 1).onTapGesture { model.selectedTab = .Explore }
Spacer()
Text("Network").border(Color.black, width: 1).onTapGesture { model.selectedTab = .Network }
Spacer()
}
}
}
struct AViewWhichNavigates: View {
@Binding var model:TabModel
var body: some View {
NavigationView(content: {
NavigationLink(destination: Text("We are one level deep in navigation in \(model.selectedTab.rawValue)"), isActive: $model.isActive) {
Text("You are at root of \(model.selectedTab.rawValue). Tap to navigate").navigationTitle(model.selectedTab.rawValue)
}.onDisappear {
UINavigationBar.setAnimationsEnabled(model.isActive)
}
})
}
}
struct TabModel {
var selectedTab:TabName = .Explore
var isActive : Bool {
get {
switch selectedTab {
case .Explore : return tabMap.0
case .Network : return tabMap.1
}
}
set {
switch selectedTab {
case .Explore : nOn(isActive, newValue); tabMap.0 = newValue;
case .Network : nOn(isActive, newValue); tabMap.1 = newValue;
}
}
}
//tuple used to represent a fixed set of tab isActive navigation states
var tabMap = (false, false)
func nOn(_ old:Bool,_ new:Bool ){
UINavigationBar.setAnimationsEnabled(new && !old)
}
}
推荐阅读
- dictionary - 通过python从嵌套字典中提取数据
- php - 如何解决错误:1416F086:在 PHP 服务器中?
- ansible - 如何通过 ansible 获取 vmware 数据存储标签
- dart - Dart - 如何发送带括号的查询参数数组
- android - 无法解析 Mapbox 依赖项
- c# - 在 C# 中处理具有大量非常相似的类的多态性
- excel - Excel图表上的自定义x轴
- html - 预加载字体时不能让所有浏览器都满意 - 控制台错误
- sql - 用 SQL 解码(请帮助理解这段代码)
- karate - 如何启用通过空手道 ChromeDriver 下载 PDF 文件?