SwiftUI Present View модально через TabView?

У меня TabView настроен следующим образом:

struct ContentView: View {
    @State private var selection = 0
    @State var newListingPresented = false

    var body: some View {
        TabView(selection: $selection){

            // Browse
            BrowseView()
                .tabItem {
                    VStack {
                        Image(systemName: (selection == 0 ? "square.grid.2x2.fill" : "square.grid.2x2"))
                    }
                }
                .tag(0)


            // New Listing
            NewListingView()
                .tabItem {
                    VStack {
                        Image(systemName: (selection == 1 ? "plus.square.fill" : "plus.square"))
                    }
                }
                .tag(1)

            // Bag
            BagView()
                .tabItem {
                    VStack {
                        Image(systemName: (selection == 2 ? "bag.fill" : "bag"))
                    }
                }
                .tag(2)

            // Profile
            ProfileView()
                .tabItem {
                    VStack {
                        Image(systemName: (selection == 3 ? "person.crop.square.fill" : "person.crop.square"))
                    }
                }
                .tag(3)
        }.edgesIgnoringSafeArea(.top)
    }
}

Вопрос: Как сделать так, чтобы вкладка «Новое объявление» отображалась NewListingView модально (в SwiftUI это называется листом?) при нажатии?


person Steven Schafer    schedule 26.12.2019    source источник


Ответы (2)


Если я правильно понял вашу цель, вы могли бы рассмотреть следующий подход, основанный на идее использования представления оболочки объекта, который будет представлять целевой вид в виде листа ...

Вот оно:

struct SheetPresenter<Content>: View where Content: View {
    @Binding var presentingSheet: Bool
    var content: Content
    var body: some View {
        Text("")
            .sheet(isPresented: self.$presentingSheet, content: { self.content })
            .onAppear {
                DispatchQueue.main.async {
                    self.presentingSheet = true
                }
            }
    }
}

и использование в вашем случае ...

// New Listing
    SheetPresenter(presentingSheet: $newListingPresented, content: NewListingView())
    .tabItem {
        VStack {
            Image(systemName: (selection == 1 ? "plus.square.fill" : "plus.square"))
        }
    }
    .tag(1)

Если вам нужно будет изменить вкладку selection после работы с листом, вы можете передать дополнительный аргумент в SheetPresenter и использовать его в обратном вызове onDismiss: (() -> Void)? листа.

person Asperi    schedule 26.12.2019
comment
Хороший! Однако есть одно предложение: вы могли бы использовать компонент Rectangle вместо этого пустого Text в теле SheetPresenter. - person nayem; 26.12.2019
comment
Спасибо! Это прекрасно работает. Не могли бы вы приложить пример того, как я могу изменить вкладку selection на закрытии листа? - person Steven Schafer; 27.12.2019
comment
Вы можете использовать что угодно вместо текста или прямоугольника. Я предпочитаю использовать Color.clear для этой цели - person ramzesenok; 10.01.2021

Я думаю, вы ищете это решение. Вы делаете пустой tabItem (Text(" ")), устанавливаете Image в нужную позицию и используете .onTapGesture. В этом ответе я просто показываю, как подавать ActionSheet.

person Александр Грабо&    schedule 26.12.2019