Функция полезности средней кнопки панели вкладок в SwiftUI - PullRequest
0 голосов
/ 25 февраля 2020

Я пытаюсь воспроизвести «Instagram», такой как tabBar, в центре которого есть кнопка «Утилита», которая не обязательно принадлежит экосистеме tabBar.

Я прикрепил этот GIF-файл, чтобы показать поведение, за которым я следую. Чтобы описать проблему. Панель вкладок посередине (черный плюс) - это щелчок. Представлен ActionSheet ВМЕСТО переключающего представления.

enter image description here

Как бы это сделать в UIKit просто используйте функцию

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

из UITabBarDelegate. Но, очевидно, мы не можем сделать это в SwiftUI, поэтому смотрели, есть ли какие-то идеи, которые люди пробовали. Моей последней мыслью было бы просто обернуть его в UIView и использовать его с SwiftUI, но я хотел бы избежать этого и оставить его родным.

Я видел запись в пользовательском TabBar, но хотел бы использовать TabBar, предоставленный Apple, чтобы избежать любых будущих расхождений.

Спасибо!

Редактировать: уточните вопрос.

Ответы [ 2 ]

2 голосов
/ 27 февраля 2020

Спасибо Алески за отличный ответ (помечено как правильное). Я развил это немного в дополнение к medium статье, которая была написана вокруг Модального. Я обнаружил, что это немного отличается

Вот jist.

MainTabBarData, который является наблюдаемым объектом

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.

2 голосов
/ 25 февраля 2020

Вы можете ввести новое свойство @State для хранения старого тега представленной вкладки. И выполните следующий метод для каждой из ваших вкладок .onAppear { self.oldSelectedItem = self.selectedItem }, за исключением средней вкладки. Средняя вкладка будет отвечать за отображение листа действий, а его метод будет выглядеть следующим образом:

.onAppear { 
self.shouldShowActionSheet.toggle() 
self.selectedItem = self.oldSelectedItem
}

Рабочий пример:

import SwiftUI

struct ContentView: View {
    @State private var selectedItem = 1
    @State private var shouldShowActionSheet = false
    @State private var oldSelectedItem = 1

    var body: some View {
        TabView (selection: $selectedItem) {
            Text("Home")
                .tabItem { Image(systemName: "house") }
                .tag(1)
                .onAppear { self.oldSelectedItem = self.selectedItem }
            Text("Search")
                .tabItem { Image(systemName: "magnifyingglass") }
                .tag(2)
                .onAppear { self.oldSelectedItem = self.selectedItem }
            Text("Add")
                .tabItem { Image(systemName: "plus.circle") }
                .tag(3)
                .onAppear {
                    self.shouldShowActionSheet.toggle()
                    self.selectedItem = self.oldSelectedItem
                }
            Text("Heart")
                .tabItem { Image(systemName: "heart") }
                .tag(4)
                .onAppear { self.oldSelectedItem = self.selectedItem }
            Text("Profile")
                .tabItem { Image(systemName: "person.crop.circle") }
                .tag(5)
                .onAppear { self.oldSelectedItem = self.selectedItem }
        }
        .actionSheet(isPresented: $shouldShowActionSheet) { ActionSheet(title: Text("Title"), message: Text("Message"), buttons: [.default(Text("Option 1"), action: option1), .default(Text("Option 2"), action: option2) , .cancel()]) }
    }

    func option1() {
        // do logic 1
    }

    func option2() {
        // do logic 2
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
...