在SwiftUI中使用包装的UIKit标签视图在按钮按下时切换标签

时间:2020-06-22 19:25:53

标签: ios swift swiftui

我在按SocialView()上的按钮时尝试切换到另一个选项卡(例如WorkOutView())。但是,我一直在SwiftUI中使用UIKit tabview的包装结构。

包装器:

struct UIKitStyleTabView: View {
    var viewControllers: [HostingController<AnyView>]
    
    //@State var switchTab = 0

    struct Tab {
        var view: AnyView
        var barItem: UITabBarItem

        init<V: View>(view: V, barItem: UITabBarItem) {
            self.view = AnyView(view)
            self.barItem = barItem
        }
    }

    init(_ tabs: [Tab]) {
        self.viewControllers = tabs.map {
            let host = HostingController(rootView: $0.view)
            host.tabBarItem = $0.barItem
            return host
        }
    }

    var body: some View {
        TabBarController(controllers: viewControllers, switchTab: $switchTab)
            .edgesIgnoringSafeArea(.all)
    }
}

struct TabBarController: UIViewControllerRepresentable {
    var controllers: [UIViewController]

    @Binding var switchTav: Int

    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = controllers
        return tabBarController
    }

    func updateUIViewController(_ uiViewController: UITabBarController, context: Context) {
        //uiViewController.selectedIndex = switchTab
    }
}

我这样设置:

struct MainView : View {
    //@Binding var switchTab: Int
    
    let tabBarSymbolConfig = UIImage.SymbolConfiguration(scale: .medium)
    
    var body : some View {
        
            UIKitStyleTabView([
                UIKitStyleTabView.Tab(view: SocialView(switchTab: $switchTab).accentColor(.white), barItem: UITabBarItem(title: "Social", image: UIImage(systemName: "person.3.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
                ), UIKitStyleTabView.Tab(view: SearchView().accentColor(.white), barItem: UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
                ), UIKitStyleTabView.Tab(view: WorkoutsView().accentColor(.white),barItem: UITabBarItem(title: "Workouts", image: UIImage(systemName: "doc.on.clipboard.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
               ), UIKitStyleTabView.Tab(view: ExercisesView().accentColor(.white), barItem: UITabBarItem(title: "Exercises", image: UIImage(systemName: "sportscourt", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
                ), UIKitStyleTabView.Tab(view: AccountView().accentColor(.white), barItem: UITabBarItem(title: "Me", image: UIImage(systemName: "person.crop.circle", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
                )
            ], switchTab: $switchTab).accentColor(.navIconColor)
        

我试图在连接这些视图的所有位置插入一个状态/绑定变量,以便可以在updateUIViewController函数中使用它,但这并没有真正起作用,因为我最终不得不在SceneDelegate中插入一个Binding。 / p>

任何建议如何实现这一目标?

1 个答案:

答案 0 :(得分:1)

这是经过纠正和工作的变体(由于缺少许多组件而已被复制,因此需要您适应)。

通过Xcode 11.4 / iOS 13.4测试

demo

完整的模块代码:

struct UIKitStyleTabView: View {
    var viewControllers: [UIHostingController<AnyView>]

    @Binding var switchTab: Int

    struct Tab {
        var view: AnyView
        var barItem: UITabBarItem

        init<V: View>(view: V, barItem: UITabBarItem) {
            self.view = AnyView(view)
            self.barItem = barItem
        }
    }

    init(_ tabs: [Tab], switchTab: Binding<Int>) {
        self.viewControllers = tabs.map {
            let host = UIHostingController(rootView: $0.view)
            host.tabBarItem = $0.barItem
            return host
        }
        self._switchTab = switchTab
    }

    var body: some View {
        TabBarController(controllers: viewControllers, switchTab: $switchTab)
            .edgesIgnoringSafeArea(.all)
    }
}

struct TabBarController: UIViewControllerRepresentable {
    var controllers: [UIViewController]

    @Binding var switchTab: Int

    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = controllers
        tabBarController.delegate = context.coordinator
        return tabBarController
    }

    func updateUIViewController(_ uiViewController: UITabBarController, context: Context) {
        uiViewController.selectedIndex = switchTab
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITabBarControllerDelegate {
        let owner: TabBarController
        init(_ owner: TabBarController) {
            self.owner = owner
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            owner.switchTab = tabBarController.selectedIndex
        }
    }
}

struct TabsMainView : View {
    @State var switchTab: Int = 0

    let tabBarSymbolConfig = UIImage.SymbolConfiguration(scale: .medium)

    var body : some View {

        UIKitStyleTabView([
            UIKitStyleTabView.Tab(view: SocialView(switchTab: $switchTab).accentColor(.white), barItem: UITabBarItem(title: "Social", image: UIImage(systemName: "person.3.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("SearchView").accentColor(.white), barItem: UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("WorkoutsView").accentColor(.white),barItem: UITabBarItem(title: "Workouts", image: UIImage(systemName: "doc.on.clipboard.fill", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("ExercisesView").accentColor(.white), barItem: UITabBarItem(title: "Exercises", image: UIImage(systemName: "sportscourt", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            ), UIKitStyleTabView.Tab(view: Text("AccountView").accentColor(.white), barItem: UITabBarItem(title: "Me", image: UIImage(systemName: "person.crop.circle", withConfiguration: tabBarSymbolConfig)!.withBaselineOffset(fromBottom: 4.5), selectedImage: nil)
            )
        ], switchTab: $switchTab)//.accentColor(.navIconColor)
    }
}

struct SocialView: View {
    @Binding var switchTab: Int

    var body: some View {
        Button("Go Search") { self.switchTab = 1 }
    }
}

struct TabsMainView_Previews: PreviewProvider {
    static var previews: some View {
        TabsMainView().colorScheme(.dark)
    }
}