SwiftUI TabView:从不同视图设置选定的 tabItem 但检测重复选择
SwiftUI TabView: Set selected tabItem from different view but detecting repeated selection
我想显示一个 TabView
以显示不同的屏幕。我的第一个屏幕(主页)显示三个按钮,它们可以 select 显示三个屏幕中的一个。
但是(!)我必须检查一个选项卡是否被重复 selected 以触发在这种情况下的特殊操作。
对 screen2 的重复 selection 的检测工作正常,但我无法通过按钮设置 selection。
我尝试使用 @EnvironmentalObject
但在我的 TabView.selection.
中没有观察到对此对象的更改
import SwiftUI
@main
struct TestApp: App {
static let kIndex0 = 0
static let kIndex1 = 1
static let kIndex2 = 2
var appState = AppState()
@State private var selection = TestApp.kIndex0
var body: some Scene {
// this code is required to detect a repeated selection of
// the same tab to trigger a special action
let index = Binding<Int>(
get: { self.selection },
set: {
if [=10=] == TestApp.kIndex1 && self.selection == [=10=] {
print("Trigger special action for index 1")
}
print("Pressed tab: \([=10=]) self.selction: \(self.selection) app.selectedTab: \(appState.selectedTab)")
self.selection = [=10=]
appState.selectedTab = [=10=]
})
WindowGroup {
TabView(selection: index) {
First()
.environmentObject(appState)
.tabItem {
Image(systemName: "1.circle")
Text("Home")
}.tag(TestApp.kIndex0)
Text("Second Content View")
.tabItem {
Image(systemName: "2.circle")
Text("Screen Two")
}.tag(TestApp.kIndex1)
Text("Third Content View")
.tabItem {
Image(systemName: "3.circle")
Text("Screen Three")
}.tag(TestApp.kIndex2)
}
}
}
}
class AppState: ObservableObject {
@Published var selectedTab = TestApp.kIndex0
}
/*
Place to buttons which should select on of the the two
tabs of TestUI
*/
struct First: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack(alignment: .leading, spacing: 20) {
AButton(tabIndex: TestApp.kIndex0, iconName: "1.circle", text: "This first screen")
.environmentObject(appState)
AButton(tabIndex: TestApp.kIndex1, iconName: "2.circle", text: "Second screen")
.environmentObject(appState)
AButton(tabIndex: TestApp.kIndex1, iconName: "3.circle", text: "Third screen")
.environmentObject(appState)
}
}
}
struct AButton: View {
let tabIndex: Int
let iconName: String
let text: String
@EnvironmentObject var appState: AppState
var body: some View {
Button(action: {
appState.selectedTab = tabIndex
}) {
HStack() {
Image(systemName: iconName)
.imageScale(.large)
.frame(minWidth: 50)
Text(text)
}
}
}
}
你需要让 appState
被观察到,你根本不需要 selection
(它只是一个副本)。
我把所有的东西都分开了ContentView
(留个场景只放场景)
测试 Xcode 12 / iOS 14
struct ContentView: View {
@StateObject var appState = AppState()
var body: some View {
// this code is required to detect a repeated selection of
// the same tab to trigger a special action
let index = Binding<Int>(
get: { self.appState.selectedTab },
set: {
if [=10=] == TestApp.kIndex1 && self.appState.selectedTab == [=10=] {
print("Trigger special action for index 1")
}
print("Pressed tab: \([=10=]) app.selectedTab: \(appState.selectedTab)")
appState.selectedTab = [=10=]
})
TabView(selection: index) {
First()
.environmentObject(appState)
.tabItem {
Image(systemName: "1.circle")
Text("Home")
}.tag(TestApp.kIndex0)
Text("Second Content View")
.tabItem {
Image(systemName: "2.circle")
Text("Screen Two")
}.tag(TestApp.kIndex1)
Text("Third Content View")
.tabItem {
Image(systemName: "3.circle")
Text("Screen Three")
}.tag(TestApp.kIndex2)
}
}
}
class AppState: ObservableObject {
@Published var selectedTab = TestApp.kIndex0
}
struct First: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack(alignment: .leading, spacing: 20) {
AButton(tabIndex: TestApp.kIndex0, iconName: "1.circle", text: "This first screen")
AButton(tabIndex: TestApp.kIndex1, iconName: "2.circle", text: "Second screen")
AButton(tabIndex: TestApp.kIndex2, iconName: "3.circle", text: "Third screen")
}
}
}
struct AButton: View {
let tabIndex: Int
let iconName: String
let text: String
@EnvironmentObject var appState: AppState
var body: some View {
Button(action: {
appState.selectedTab = tabIndex
}) {
HStack() {
Image(systemName: iconName)
.imageScale(.large)
.frame(minWidth: 50)
Text(text)
}
}
}
}
我想显示一个 TabView
以显示不同的屏幕。我的第一个屏幕(主页)显示三个按钮,它们可以 select 显示三个屏幕中的一个。
但是(!)我必须检查一个选项卡是否被重复 selected 以触发在这种情况下的特殊操作。
对 screen2 的重复 selection 的检测工作正常,但我无法通过按钮设置 selection。
我尝试使用 @EnvironmentalObject
但在我的 TabView.selection.
import SwiftUI
@main
struct TestApp: App {
static let kIndex0 = 0
static let kIndex1 = 1
static let kIndex2 = 2
var appState = AppState()
@State private var selection = TestApp.kIndex0
var body: some Scene {
// this code is required to detect a repeated selection of
// the same tab to trigger a special action
let index = Binding<Int>(
get: { self.selection },
set: {
if [=10=] == TestApp.kIndex1 && self.selection == [=10=] {
print("Trigger special action for index 1")
}
print("Pressed tab: \([=10=]) self.selction: \(self.selection) app.selectedTab: \(appState.selectedTab)")
self.selection = [=10=]
appState.selectedTab = [=10=]
})
WindowGroup {
TabView(selection: index) {
First()
.environmentObject(appState)
.tabItem {
Image(systemName: "1.circle")
Text("Home")
}.tag(TestApp.kIndex0)
Text("Second Content View")
.tabItem {
Image(systemName: "2.circle")
Text("Screen Two")
}.tag(TestApp.kIndex1)
Text("Third Content View")
.tabItem {
Image(systemName: "3.circle")
Text("Screen Three")
}.tag(TestApp.kIndex2)
}
}
}
}
class AppState: ObservableObject {
@Published var selectedTab = TestApp.kIndex0
}
/*
Place to buttons which should select on of the the two
tabs of TestUI
*/
struct First: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack(alignment: .leading, spacing: 20) {
AButton(tabIndex: TestApp.kIndex0, iconName: "1.circle", text: "This first screen")
.environmentObject(appState)
AButton(tabIndex: TestApp.kIndex1, iconName: "2.circle", text: "Second screen")
.environmentObject(appState)
AButton(tabIndex: TestApp.kIndex1, iconName: "3.circle", text: "Third screen")
.environmentObject(appState)
}
}
}
struct AButton: View {
let tabIndex: Int
let iconName: String
let text: String
@EnvironmentObject var appState: AppState
var body: some View {
Button(action: {
appState.selectedTab = tabIndex
}) {
HStack() {
Image(systemName: iconName)
.imageScale(.large)
.frame(minWidth: 50)
Text(text)
}
}
}
}
你需要让 appState
被观察到,你根本不需要 selection
(它只是一个副本)。
我把所有的东西都分开了ContentView
(留个场景只放场景)
测试 Xcode 12 / iOS 14
struct ContentView: View {
@StateObject var appState = AppState()
var body: some View {
// this code is required to detect a repeated selection of
// the same tab to trigger a special action
let index = Binding<Int>(
get: { self.appState.selectedTab },
set: {
if [=10=] == TestApp.kIndex1 && self.appState.selectedTab == [=10=] {
print("Trigger special action for index 1")
}
print("Pressed tab: \([=10=]) app.selectedTab: \(appState.selectedTab)")
appState.selectedTab = [=10=]
})
TabView(selection: index) {
First()
.environmentObject(appState)
.tabItem {
Image(systemName: "1.circle")
Text("Home")
}.tag(TestApp.kIndex0)
Text("Second Content View")
.tabItem {
Image(systemName: "2.circle")
Text("Screen Two")
}.tag(TestApp.kIndex1)
Text("Third Content View")
.tabItem {
Image(systemName: "3.circle")
Text("Screen Three")
}.tag(TestApp.kIndex2)
}
}
}
class AppState: ObservableObject {
@Published var selectedTab = TestApp.kIndex0
}
struct First: View {
@EnvironmentObject var appState: AppState
var body: some View {
VStack(alignment: .leading, spacing: 20) {
AButton(tabIndex: TestApp.kIndex0, iconName: "1.circle", text: "This first screen")
AButton(tabIndex: TestApp.kIndex1, iconName: "2.circle", text: "Second screen")
AButton(tabIndex: TestApp.kIndex2, iconName: "3.circle", text: "Third screen")
}
}
}
struct AButton: View {
let tabIndex: Int
let iconName: String
let text: String
@EnvironmentObject var appState: AppState
var body: some View {
Button(action: {
appState.selectedTab = tabIndex
}) {
HStack() {
Image(systemName: iconName)
.imageScale(.large)
.frame(minWidth: 50)
Text(text)
}
}
}
}