button - SwiftUI TabView : Set selected tabItem from different view but detecting repeated selection

标签 button swiftui controls tabview

我想显示一个 TabView以显示不同的屏幕。我的第一个屏幕(主页)显示三个按钮,可以选择要显示的三个屏幕之一。
但是(!)我必须检查是否重复选择了一个选项卡以在这种情况下触发特殊操作。
检测 screen2 的重复选择工作正常,但我无法通过按钮设置选择。
我试过使用 @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 $0 == TestApp.kIndex1  &&  self.selection == $0 {
                       print("Trigger special action for index 1")
                   }
                   print("Pressed tab: \($0)  self.selction: \(self.selection)  app.selectedTab: \(appState.selectedTab)")

                   self.selection = $0
                   appState.selectedTab = $0
               })

           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 $0 == TestApp.kIndex1  &&  self.appState.selectedTab == $0 {
                    print("Trigger special action for index 1")
                }
                print("Pressed tab: \($0) app.selectedTab: \(appState.selectedTab)")
                appState.selectedTab = $0
            })

        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)
            }
        }
    }
}

关于button - SwiftUI TabView : Set selected tabItem from different view but detecting repeated selection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63734984/

相关文章:

ios - 如何在 View 上继续动画刷新控件已更改

javascript - 每次我在 <body> 中单击鼠标时,我创建的函数都会运行

html - Angular Material 按钮上的超链接不会导致浏览器跳转到该链接

swift - 如何在 SwiftUI 中创建字符串的大写版本?

swift - 使用 CoreData 在 SwiftUI 中填充列表

swiftui - @Observable 类成员不触发 UI 更新

wolfram-mathematica - 在 Mathematica 中使用 Manipulate 控制放置

asp.net - 在 asp :Button 中换行文本

安卓-FragmentStatePagerAdapter : trigger swipe manually/disable swipe

安卓日历 "Grid of Dates"