首页 > 解决方案 > SwiftUI 中的 Tabbar 中间按钮实用功能

问题描述

我正在尝试复制一个“Instagram” tabBar,其中中间有一个“实用程序”按钮,不一定属于tabBar生态系统。

我附上了这个 gif 来展示我所追求的行为。来描述问题。中间的标签栏(黑色加号)是单击一个 ActionSheet 而不是切换视图。

在此处输入图像描述

我如何在 UIKit 中做到这一点只是使用

override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
    print("Selected item")
}

函数来自UITabBarDelegate. 但显然我们不能在 SwiftUI 中做到这一点,所以我们想看看人们是否尝试过任何想法。我最后的想法是将它简单地包装在 UIView 中并将其与 SwiftUI 一起使用,但希望避免这种情况并保持原生状态。

我在自定义 TabBar 中看到了一篇文章,但想使用 Apple 提供的 TabBar 以避免将来出现任何差异。

谢谢!

编辑:使问题更清楚。

标签: swiftuikitswiftuitabbar

解决方案


感谢Aleskey的出色回答(标记为正确)。除了围绕 Modal 编写的中篇文章之外,我对它进行了一些改进。我发现它有点不同

这是吉斯特。

MainTabBarData 是一个 Observable 对象

final class MainTabBarData: ObservableObject {

    /// This is the index of the item that fires a custom action
    let customActiontemindex: Int

    let objectWillChange = PassthroughSubject<MainTabBarData, Never>()

    var previousItem: Int

    var itemSelected: Int {
        didSet {
            if itemSelected == customActiontemindex {
                previousItem = oldValue
                itemSelected = oldValue
                isCustomItemSelected = true
            }
            objectWillChange.send(self)
        }
    }

    func reset() {
        itemSelected = previousItem
        objectWillChange.send(self)
    }

    /// This is true when the user has selected the Item with the custom action
    var isCustomItemSelected: Bool = false

    init(initialIndex: Int = 1, customItemIndex: Int) {
        self.customActiontemindex = customItemIndex
        self.itemSelected = initialIndex
        self.previousItem = initialIndex
    }
}

这是 TabbedView

struct TabbedView: View {

    @ObservedObject private var tabData = MainTabBarData(initialIndex: 1, customItemIndex: 2)


    var body: some View {

        TabView(selection: $tabData.itemSelected) {
            Text("First Screen")
                .tabItem {
                    VStack {
                        Image(systemName: "globe")
                            .font(.system(size: 22))
                        Text("Profile")
                    }

                }.tag(1)

            Text("Second Screen")
                .tabItem {
                    VStack {
                        Image(systemName: "plus.circle")
                            .font(.system(size: 22))
                        Text("Profile")
                    }
            }.tag(2)

            Text("Third Screen")
                .tabItem {
                    VStack {
                        Image(systemName: "number")
                            .font(.system(size: 22))
                        Text("Profile")
                    }
            }.tag(3)

        }.actionSheet(isPresented: $tabData.isCustomItemSelected) {
            ActionSheet(title: Text("SwiftUI ActionSheet"), message: Text("Action Sheet Example"),
                        buttons: [
                            .default(Text("Option 1"), action: option1),
                            .default(Text("Option 2"), action: option2),
                            .cancel(cancel)
                        ]
            )
        }



    }

    func option1() {
        tabData.reset()
        // ...
    }

    func option2() {
        tabData.reset()
        // ...
    }

    func cancel() {
        tabData.reset()
    }
}

struct TabbedView_Previews: PreviewProvider {
    static var previews: some View {
        TabbedView()
    }
}

类似的概念,只是使用了 SwiftUI 和 Combine 的强大功能。


推荐阅读