SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡?

2024-01-25

我正在尝试添加不同的toolbars 到我的每个选项卡,但它们没有显示。该应用程序主要在横向 iPad 上使用,我可以将工具栏添加到TabView本身并显示,但我不知道如何将按下导航堆栈的按钮传递到要在本地处理的各个视图/视图模型。

我尝试过添加新的NavigationViews(包括.stack navigationViewStyles) 但这仍然只是在视图中添加了另一列。

这是一些准系统的工作代码:

import SwiftUI

@main
struct NavTabTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
            MasterView()
    }
}

struct MasterView: View {
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<20) { index in
                    NavigationLink(
                        destination: DetailView(index: index)
                            .navigationTitle("Row \(index)")
                    ) {
                        Text("\(index) th row")
                    }.tag(index)
                }
            }.navigationTitle(Text("Ratty"))
        }
    }
}

struct DetailView: View {
    var index: Int
    
    @State var selectedTab = 1
    
    var body: some View {
        TabView(selection: $selectedTab) {
            Tab1(index: index).tabItem { Label("Tab1", systemImage: "list.dash") }
            Tab2(index: index).tabItem { Label("Tab2", systemImage: "aqi.medium") }
            Tab3(index: index).tabItem { Label("Tab3", systemImage: "move.3d") }
        }
    }
}

struct Tab1: View {    
    var index: Int
    
    var body: some View {
        Text("This is \(index) in tab 1")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button("Bingo") { print("Bingo") }
                }
            }
    }
}

struct Tab2: View {
    var index: Int
    
    var body: some View {
        Text("This is \(index) in tab 2")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button("Bongo") { print("Bongo") }
                }
            }
    }
}

struct Tab3: View {
    var index: Int
    
    var body: some View {
        Text("This is \(index) in tab 3")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button("Banjo") { print("Banjo") }
                }
            }
    }
}

我开始想知道这是否可能,以及使用每个选项卡顶部的按钮实现我自己的视图是否会更好。

EDIT:


您只需要使用一个级别NavigationView。换句话说,你不应该嵌套NavigationViews。看看这个答案。

自定义导航栏 SwiftUI 上仅可见后退按钮 https://stackoverflow.com/questions/68117105/only-back-button-visible-on-custom-navigation-bar-swiftui


  1. Use a NavgationView为了MasterView正如你所使用的。
  2. Use a NavigationView对于每个Tab# veiws.
  3. 之间切换MasterView and DetailsView.
  4. Use Button代替NavigationLink in MasterView(您可以将其自定义为看起来像NavigationLink)
  5. 在每个中使用自定义后退按钮Tab# veiws.

这控制哪一个MasterView and DetailsView应该显示。

class BaseViewModel: ObservableObject {
    @Published var userFlow: UserFlow = .masterView
    
    init(){
        userFlow = .masterView
    }
    
    enum UserFlow {
        case masterView, detailsView
    }
}

该视图可用于ContentView或者代替它。当你在MasterView然后单击列表行之一,设置appState.userFlow = .detailView。当您单击后退按钮时,设置appState.userFlow = .masterView.

这样做,您可以在两个视图和一个视图之间切换NavigationView一次显示。

截至目前,它还没有动画。如果您愿意,请使用

https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions

struct BaseView: View {
    
    @EnvironmentObject var appState: BaseViewModel
    
    @State var index: Int = 0
    
    var body: some View {
        Group {
            switch appState.userFlow {
            case .masterView:
                MasterView(index: $index)
            default:
                DetailView(index: index)
            }
        }
        .edgesIgnoringSafeArea(.bottom)
    }
}


完整代码

struct ContentView: View {
    var body: some View {
        BaseView().environmentObject(BaseViewModel())
    }
}


class BaseViewModel: ObservableObject {
    @Published var userFlow: UserFlow = .masterView
    
    init(){
        userFlow = .masterView
    }
    
    enum UserFlow {
        case masterView, detailsView
    }
}


struct BaseView: View {
    
    @EnvironmentObject var appState: BaseViewModel
    
    @State var index: Int = 0
    
    var body: some View {
        Group {
            switch appState.userFlow {
            case .masterView:
                MasterView(index: $index)
            default:
                DetailView(index: index)
            }
        }
        .edgesIgnoringSafeArea(.bottom)
    }
}


struct MasterView: View {
    @EnvironmentObject var appState: BaseViewModel
    
    @Binding var index: Int
    
    var body: some View {
        NavigationView {
            List {
                ForEach(0..<20) { index in
                    Button(action: {
                        appState.userFlow = .detailsView
                        $index.wrappedValue = index
                    }, label: {
                        HStack {
                            Text("\(index) th row")
                            Spacer()
                            Image(systemName: "greaterthan")
                        }
                    })
                    .tag(index)
                }
            }.navigationTitle(Text("Ratty"))
        }
    }
}

struct DetailView: View {
    var index: Int
    
    @State var selectedTab = 1
    
    var body: some View {
        TabView(selection: $selectedTab) {
            Tab1(index: index).tabItem { Label("Tab1", systemImage: "list.dash") }
            Tab2(index: index).tabItem { Label("Tab2", systemImage: "aqi.medium") }
            Tab3(index: index).tabItem { Label("Tab3", systemImage: "move.3d") }
        }
    }
}

struct Tab1: View {
    @EnvironmentObject var appState: BaseViewModel
    
    var index: Int
    
    var body: some View {
        NavigationView {
            Text("This is \(index) in tab 1")
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("back") { appState.userFlow = .masterView  }
                    }
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button("Bingo") { print("Bingo") }
                    }
                }
        }
    }
}

struct Tab2: View {
    @EnvironmentObject var appState: BaseViewModel
    
    var index: Int
    
    var body: some View {
        NavigationView {
            Text("This is \(index) in tab 2")
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("back") { appState.userFlow = .masterView  }
                    }
                    ToolbarItem(placement: .primaryAction) {
                        Button("Bongo") { print("Bongo") }
                    }
                }
        }
    }
}

struct Tab3: View {
    @EnvironmentObject var appState: BaseViewModel
    var index: Int
    
    var body: some View {
        NavigationView {
            Text("This is \(index) in tab 3")
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button("back") { appState.userFlow = .masterView  }
                    }
                    ToolbarItem(placement: .primaryAction) {
                        Button("Banjo") { print("Banjo") }
                    }
                }
        }
    }
}


我已经定制了xtwistedx https://stackoverflow.com/users/12417531/xtwistedx 's solution https://stackoverflow.com/questions/68117105/only-back-button-visible-on-custom-navigation-bar-swiftui.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡? 的相关文章

  • SwiftUI 是否可以调用该函数并从其他页面更改视图?

    这是我的代码 struct FirstPage View var body some View VStack NavigationView VStack Text First Page bold NavigationLink destina
  • SwiftUI Focus State API 环境变量不起作用

    当我们想要观察 SwiftUI 文本字段的焦点状态时 环境值 isFocused 似乎不起作用 除了将值传递给 TextFieldStyle 的 init 我们必须为每个 Textfield 执行此操作 之外 还有其他方法可以做到这一点吗
  • 在 SwiftUI (5) 和 Xcode (12.4) 中实现 AdMob 插页式广告

    我正在努力在我的应用程序中实现插页式广告 但对 AdMob 提供的文档和新的 SwiftUI 应用程序结构遇到了一些困惑 这里是app swift文件 显示我已经实现了 GoogleMobileAds 并在didFinishLaunchin
  • SwiftUI:类型不符合协议“UIViewRepresentable”//我的代码

    我正在开发一个新的 SwiftUI 应用程序 我正在尝试弄清楚如何使这个 Swift 项目与 SwiftUI 兼容 在此示例中 我正在开发带有方向的地图 问题是我无法使 UIViewRepresentable 工作 我收到错误 类型 Dir
  • 更改 TabBar SwiftUI 中的选项卡选择颜色

    我试图更改 TabBar 中选定选项卡的颜色 但没有任何效果 我可以更改 TabBarbackgroundColor通过写作 struct ContentView View init UITabBar appearance backgrou
  • 如何修复 getActionBar 方法可能产生 java.lang.NullPointerException

    我在活动中使用工具栏作为操作栏 我正在尝试添加方法getActionBar setDisplayHomeAsUpEnabled true 到 Activity java 文件 用于旧设备的向上导航 该方法在 Android Studio 中
  • 在 SwiftUI 中正确组合 TabView 与 PageTabViewStyle、NavigationView 和 ScrollView

    我正在开发一个将 TabView 与 PageTabViewStyle NavigationView 和 ScrollView 结合在一起的 UI 向下滚动时 我希望 NavigationView 的标题能够调整并变小 但当 ScrollV
  • 在 SecureField 的 SwiftUI 中切换 isSecureTextEntry

    我想实现在 SecureField 中显示和隐藏密码的功能 以下是 SecureField 的代码 我添加了按钮 该按钮将被检测到显示和隐藏 SecureField 中的文本 但 swiftUI 没有类似的功能是安全文本条目除了切换之外还有
  • SwiftUI |选择器 - 更改选定行的颜色

    我想更改所选行的颜色 正如您所看到的 默认情况下它具有浅灰色 我不知道该怎么做 因为我根本找不到访问这一行的方法 有什么办法可以做到这一点吗 演示代码 struct ContentView View var data Array 0 20
  • SwiftUI 按钮在出现时更改文本大小

    从 GIF 中可以看出 一旦工作表完全打开 完成 按钮文本就会变大 这不仅发生在这个视图中 而且也发生在使用系统图像而不是文本的其他视图中 有谁知道问题的解决方案还是我做错了什么 我仍然对 Swift 记忆犹新 NavigationView
  • SceneDelegate 和 AppDelegate 之间的区别

    在我的 SwiftUI 项目中我看到AppDelegate文件以及SceneDelegate file 它们之间有什么区别 例如在方法之间SceneDelegate scene willConnectTo options 并在AppDele
  • SwiftUI 模态视图

    从任何类或结构中模态显示 SwiftUI 视图的最佳方式是什么 我使用 UIKit 中的 UIHostingController 有没有更好的方法只使用 SwiftUI 来做到这一点 带有用于呈现 SwiftUI 视图的按钮的 Conten
  • 将 EditText 添加到工具栏

    My Toolbar and EditText看起来像这样 我尝试将其添加为ActionView但我得到了这个结果 它基本上只是添加了我的话 点击下方 作为标题 而没有TextView 这就是我所做的 menu xml menu menu
  • SwiftUI 无法使用 navigationLink 来回导航

    请注意 在 gif 中 一旦我导航并关闭新视图 我就无法返回 这是 SwiftUI 错误还是导航链接的误用 struct ContentView View var body some View return NavigationView N
  • SwiftUI 检测按下删除按钮

    我正在使用 SwiftUI 但我正在编写自己的自定义文本掩码 但当用户按 删除 键时我需要删除 我正在使用onChange方法 但它不检测何时按下特殊键 目前我正在使用 TextField self placeholder text sel
  • 前置条件失败:从 iOS 13.4 开始,在 SwiftUI 中使用 GeometryReader 时输入索引无效

    昨天 我将 XCode 和我的项目升级到 iOS 13 4 我开始在使用 GeometryReaders 的视图周围看到很多失败 除了 前提条件失败 输入索引无效 之外 该错误没有显示任何内容 升级到 13 4 1 后我遇到了完全相同的问题
  • CoreData 和 SwiftUI:环境中的上下文未连接到持久存储协调器

    我正在尝试通过构建一个作业管理应用程序来自学核心数据 我的代码构建良好 应用程序运行正常 直到我尝试将新分配添加到列表中 我收到这个错误Thread 1 EXC BREAKPOINT code 1 subcode 0x1c25719e8 在
  • Swiftui,按钮网格视图

    我在这里检查了有关网格视图的几个问题 但我的问题有点不同 我想为按钮创建一个网格视图 以便每个按钮按下时导航到不同的视图 所以它看起来像这样 这是网格按钮视图 https i stack imgur com Q6WWB jpg 所以我在这里
  • 按下后退按钮时 SwiftUI 工具栏项目被剪裁

    我在 SwiftUI 中遇到了一种奇怪的行为 我似乎无法解决它 鉴于以下简单的示例应用程序 我遇到了这种行为 工具栏项目在初始运行时正确呈现 但导航离开并返回它会被剪切 重新创建此示例代码 内容视图 swift import SwiftUI
  • SwiftUI TabbedView 仅显示第一个选项卡的内容

    我正在尝试建立一个TabbedView使用以下简单代码 TabbedView Text Hello world tabItemLabel Text Hello Text Foo bar tabItemLabel Text Foo 运行时 两

随机推荐

  • 如果实体中没有定义标识符,Hibernate 如何在内部跟踪对象?

    根据 Hibernate 参考文档 标识符属性是严格可选的 你可以把它们放下 并让 Hibernate 在内部跟踪对象标识符 如果实体中没有定义标识符 Hibernate 如何在内部跟踪对象 进一步扩展问题 如果没有标识符 我们如何 loa
  • eval() 可以优化吗?

    eval 更改局部变量的能力给 JavaScript 优化器带来了很大的问题 我读了 javascript权威指南 这本书 eval 可以优化吗 我不明白 这并不是说eval优化 而是那些寻求优化的 JavaScript 引擎被阻止这样做e
  • 对向量的每个元素中的单词重新排序

    我想更改向量中每个元素的词序 具体来说 我想制作另一个向量 其中第一个单词现在是许多长度不同的元素的最后一个单词 Data metadata1 lt c reference1 an organism reference2 another o
  • 如何填写数据安全? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在为我的应用填写 Google Play 数据安全表单 我的应用程序使用 AdMob 并且没有其他收集用户信息的库 我该怎么填写呢 对
  • 双击 .jar 文件时“找不到主类”

    首先 我意识到这个问题应该很简单 而且很多人似乎都经历过 但是 看来我的问题可能是slightly与现有职位不同 我正在使用 NetBeans 编译 Java 应用程序 构建完成后 输出将正确进入 dist 文件夹 jar 文件就在那里 如
  • onSaveInstanceState中保存接口(Listener)

    保存实例状态 对于像 Integer Long String 等数据都可以 我只是将其放入包中 并在再次调用 onCreateView 时将其取回 但我的片段也有像下面这样的听众 public class SomeFragment exte
  • EPPlus 和 ClosedXML 库在使用 OpenXML 方面有何区别? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我试图在 ClosedXML EPPlus 和可能的 SpreadsheetLight 之间进行选择 我可能会出于哪些原因考虑选择其中之一
  • 如何调试大型 git 提交?

    好的 情况如下 几年前 我们对代码库中的多个文件进行了多项更改 并一次性全部提交 这些更改中的某个地方隐藏着一个错误 使用 git bisect 我很快就能够追踪到罪魁祸首的提交 但该提交中的更改量让我有点不那么热情了 使用 git bis
  • rshiny - 有条件的条件面板:检查列表中的项目

    我有 2 个列表 每个列表包含多个 idp id以另一个变量为条件d d1 lt as list unique df p id df d 1 d2 lt as list unique df p id df d 2 我想添加一个conditi
  • ASP.Net 5 project.json 脚本命令的完整列表? (视觉工作室 2015)

    我已经看过了ASP NET 5团队 wiki 条目项目 json 来识别哪个脚本命令可用 目前列出以下内容 scripts prebuild echo before building postbuild echo after buildin
  • 顶层例外

    我在用着topshelf http topshelf project com 当我尝试使用 i 选项安装为服务时 我收到此异常 无法将 Magnum CommandLineParser SwitchElement 类型的对象转换为 Magn
  • 为 athena 选择特定文件

    在 Athena 中创建表时 我无法使用特定文件创建表 有没有办法从给定的存储桶中选择以 year 2019 开头的所有文件 例如 s3 bucketname prefix year 2019 csv 文档对此说得很清楚 这是不允许的 Fr
  • 正则表达式使用 YYYY-MM-DD 格式验证 PHP 中的日期

    我正在尝试制作一个日期正则表达式验证器 我遇到的问题是我正在使用输入字段 date type 这在 Chrome 中就像一个魅力 它会在 Chrome 中打开类似日历的功能 但在其余部分它什么也不做 所以我决定手动输入其余部分的日期 这是我
  • 等待目标设备上线

    我最近更新到 Android Studio 2 3 现在当我尝试运行该应用程序时 模拟器无法上线 300 秒后超时 此外 该应用程序遇到了致命异常错误 OOM 我不确定如何解决该问题 或者这是否是模拟器问题的一部分 任何帮助深表感谢 再说一
  • 如何将数据从一张工作表导入到另一张工作表

    我在 Excel 中有两个不同的工作表 所有第 1 行单元格中的标题都相同 a1 id b1 名称 c1 价格 我的问题是 有没有办法将数据 如名称 从一个工作表导入到另一个工作表中 其中两个工作表中的 id 相同 eg sheet 1 s
  • 如何找到 2 个数字中的最大值(更大、更大)?

    我有两个变量value and run value 9999 run problem getscore 如何找出哪个更大 并获得更大的值 See also Find the greatest largest maximum number i
  • Thread.Sleep 与 Task.Delay?

    我知道Thread Sleep阻塞一个线程 但确实Task Delay还阻止 或者只是像Timer它对所有回调使用一个线程 当不重叠时 this https stackoverflow com questions 15341962 how
  • 如何在 git 服务器端禁用压缩?

    我有一个存储库 从中拉取需要很长时间 因为服务器几乎没有可用 RAM 并且它在交换时进行了大量操作 remote Compressing objects 24 正在发生 即使我在服务器本地克隆 网络没有那么受限 因此发送所有未压缩的数据就可
  • PHP:多维数组中的foreach

    我有一个动态表单来创建创建数组的章节和子章节 var dump POST array textfield gt array 0 gt title one 1 gt title two 2 gt title three 4 gt title
  • SwiftUI - 如何将工具栏添加到 NavigationView 内的 TabView 选项卡?

    我正在尝试添加不同的toolbars 到我的每个选项卡 但它们没有显示 该应用程序主要在横向 iPad 上使用 我可以将工具栏添加到TabView本身并显示 但我不知道如何将按下导航堆栈的按钮传递到要在本地处理的各个视图 视图模型 我尝试过