如何使用 SwiftUI 从另一个 TabBarView 触发 TabBar 视图
How to trigger a TabBar View from another TabBarView with SwiftUI
在 SwiftUI 中,我创建了一个简单的基于标签栏的视图:
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
TabView(selection: $selectedTab) {
MenuView().tabItem{
self.tabbarItem(text: "Menu", image: "list.dash")
}.tag(Tab.menu)
NewsView().tabItem{
self.tabbarItem(text: "News", image: "doc")
}.tag(Tab.news)
EmptyView().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
如下图所示:
Questions:
如何在 SwiftUI 中实现我需要的东西?
我是否使用了合适的组件来实现它?基本上,它是一个菜单和一个列表,如果点击新闻,它只会加载最新的新闻,如果从菜单中点击,它会显示过滤后的新闻。
提前致谢。
这是我为实现您在 Swift 中寻找的布局而创建的代码UI。希望这有帮助。
import SwiftUI
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
@State var showFilter: Bool = false
@State var selectedFilter: String = ""
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
TabView(selection: $selectedTab) {
NavigationView {
NewsView(filter: $selectedFilter)
.navigationBarItems(trailing: Button(action: { self.showFilter.toggle() }) {
Text("Filters")
})
.navigationBarTitle("News")
.sheet(isPresented: $showFilter) {
MenuView(selectedFilter: self.$selectedFilter)
}
}
.tabItem{
self.tabbarItem(text: "News", image: "doc")
}
.tag(Tab.news)
ViewC().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
struct MenuView: View {
@Environment(\.presentationMode) var presentationMode
var menus: [String] = ["Menu No.1", "Menu No.2", "Menu No.3"]
@Binding var selectedFilter: String
var body: some View {
List {
ForEach(menus, id: \.self) { menu in
Button(action: {
self.selectedFilter = menu
self.presentationMode.wrappedValue.dismiss()
}) {
Text("\(menu)")
}
}
}
}
}
struct NewsView: View {
@Binding var filter: String
var body: some View {
List {
if filter.count > 0 {
Text("The news is filtered using \(filter)")
}
else {
Text("The latest news is being displayed.")
}
}
}
}
struct ViewC: View {
var body: some View {
Text("Under construction")
}
}
上一个答案
要实现当前布局,您需要在 NavigationView 中嵌套 TabView。我创建了一个示例项目来测试它,下面是代码。虽然它有效,但在单击后退按钮时,我收到了以下警告:
"Trying to pop to a missing destination at /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-39.4.3/UIKit/UIKitNavigationBridge.swift:390"
因此,您可能需要重新考虑该应用程序 UI。由于菜单选项卡只是新闻选项卡的过滤器,因此有一个将菜单和新闻选项卡合二为一的 TabView。启动时,该应用程序将显示最新消息。然后,您可以在 NewsView 中为过滤器创建一个单独的视图。
import SwiftUI
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
MenuView().tabItem{
self.tabbarItem(text: "Menu", image: "list.dash")
}.tag(Tab.menu)
NewsView().tabItem{
self.tabbarItem(text: "News", image: "doc")
}.tag(Tab.news)
EmptyView().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
}
struct MenuView: View {
var menus: [String] = ["Menu No.1", "Menu No.2", "Menu No.3"]
var body: some View {
List {
ForEach(menus, id: \.self) { menu in
NavigationLink(destination: NewsView(filter: "filterString")) {
Text("\(menu)")
}
}
}
}
}
struct NewsView: View {
var filter: String = ""
var body: some View {
List {
if filter.count > 0 {
Text("The news is filtered using \(filter)")
}
else {
Text("The latest news is being displayed.")
}
}
}
}
在 SwiftUI 中,我创建了一个简单的基于标签栏的视图:
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
TabView(selection: $selectedTab) {
MenuView().tabItem{
self.tabbarItem(text: "Menu", image: "list.dash")
}.tag(Tab.menu)
NewsView().tabItem{
self.tabbarItem(text: "News", image: "doc")
}.tag(Tab.news)
EmptyView().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
如下图所示:
Questions:
如何在 SwiftUI 中实现我需要的东西?
我是否使用了合适的组件来实现它?基本上,它是一个菜单和一个列表,如果点击新闻,它只会加载最新的新闻,如果从菜单中点击,它会显示过滤后的新闻。
提前致谢。
这是我为实现您在 Swift 中寻找的布局而创建的代码UI。希望这有帮助。
import SwiftUI
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
@State var showFilter: Bool = false
@State var selectedFilter: String = ""
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
TabView(selection: $selectedTab) {
NavigationView {
NewsView(filter: $selectedFilter)
.navigationBarItems(trailing: Button(action: { self.showFilter.toggle() }) {
Text("Filters")
})
.navigationBarTitle("News")
.sheet(isPresented: $showFilter) {
MenuView(selectedFilter: self.$selectedFilter)
}
}
.tabItem{
self.tabbarItem(text: "News", image: "doc")
}
.tag(Tab.news)
ViewC().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
struct MenuView: View {
@Environment(\.presentationMode) var presentationMode
var menus: [String] = ["Menu No.1", "Menu No.2", "Menu No.3"]
@Binding var selectedFilter: String
var body: some View {
List {
ForEach(menus, id: \.self) { menu in
Button(action: {
self.selectedFilter = menu
self.presentationMode.wrappedValue.dismiss()
}) {
Text("\(menu)")
}
}
}
}
}
struct NewsView: View {
@Binding var filter: String
var body: some View {
List {
if filter.count > 0 {
Text("The news is filtered using \(filter)")
}
else {
Text("The latest news is being displayed.")
}
}
}
}
struct ViewC: View {
var body: some View {
Text("Under construction")
}
}
上一个答案
要实现当前布局,您需要在 NavigationView 中嵌套 TabView。我创建了一个示例项目来测试它,下面是代码。虽然它有效,但在单击后退按钮时,我收到了以下警告:
"Trying to pop to a missing destination at /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-39.4.3/UIKit/UIKitNavigationBridge.swift:390"
因此,您可能需要重新考虑该应用程序 UI。由于菜单选项卡只是新闻选项卡的过滤器,因此有一个将菜单和新闻选项卡合二为一的 TabView。启动时,该应用程序将显示最新消息。然后,您可以在 NewsView 中为过滤器创建一个单独的视图。
import SwiftUI
struct ContentView: View {
enum Tab: Int {
case menu, news, viewc, viewd, viewf
}
@State var selectedTab = Tab.menu
func tabbarItem(text: String, image: String) -> some View {
VStack {
Image(systemName: image)
.imageScale(.large)
Text(text)
}
}
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
MenuView().tabItem{
self.tabbarItem(text: "Menu", image: "list.dash")
}.tag(Tab.menu)
NewsView().tabItem{
self.tabbarItem(text: "News", image: "doc")
}.tag(Tab.news)
EmptyView().tabItem{
self.tabbarItem(text: "ViewC", image: "star.circle")
}.tag(Tab.viewc)
EmptyView().tabItem{
self.tabbarItem(text: "ViewD", image: "speaker")
}.tag(Tab.viewd)
EmptyView().tabItem{
self.tabbarItem(text: "ViewF", image: "person")
}.tag(Tab.viewf)
}
}
}
}
struct MenuView: View {
var menus: [String] = ["Menu No.1", "Menu No.2", "Menu No.3"]
var body: some View {
List {
ForEach(menus, id: \.self) { menu in
NavigationLink(destination: NewsView(filter: "filterString")) {
Text("\(menu)")
}
}
}
}
}
struct NewsView: View {
var filter: String = ""
var body: some View {
List {
if filter.count > 0 {
Text("The news is filtered using \(filter)")
}
else {
Text("The latest news is being displayed.")
}
}
}
}