Как представить контроллер модального представления, например, с помощью UIKit UIViewControllerTransitioningDelegate?

Я перехожу с UIKit на SwiftUI и все еще пытаюсь понять некоторые его части, особенно переходы между представлениями.

У меня есть ситуация, когда на экране отображается контроллер представления со списком, скажем, ElementsListViewController(), и при нажатии на элемент я хочу отобразить модальное окно с пользовательским интерфейсом/анимацией: появится непрозрачное наложение с анимацией альфа-значения, а белый модальный «лист» будет появляться снизу вверх.

Вот как это выглядит:

enter image description here

С UIKit я бы использовал UIViewControllerAnimatedTransitioning для этого.

Теперь я хотел бы сделать то же самое со SwiftUI, но я потерялся, что делать именно здесь.

У меня пока так:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ElementsList()
        }
    }
}

struct ElementsList: View {
    @State var elements: [String] = (0..<100).map { "Element #\($0)" }

    var body: some View {
        List(elements, id: \.self) {
            Text($0)
                .onTapGesture {
                    // what to do here to display ModalView as I want to?
                }
        }
        .listStyle(PlainListStyle())
    }
}

struct ModalView: View {
    var body: some View {
        ZStack {
            Color.black.opacity(0.8)
            Color.white
                .cornerRadius(20.0)
                .padding(.top, 150)
        }
        .ignoresSafeArea()
    }
}

Каков мой лучший вариант здесь? спасибо за помощь

Создайте свой собственный и/или используйте UIViewControllerRepresentable. Это кажется сложнее, чем есть на самом деле, но я бы хотел, чтобы вы знакомы с UIKit, это всего лишь несколько дополнительных строк, чтобы заставить его работать со SwiftUI см. здесь для начала

lorem ipsum 17.05.2022 19:46

@loremipsum Спасибо за ответ! Я знаю, что мог бы легко сделать это с помощью UIViewControllerRepresentable, но я намерен сделать это на 100% SwiftUI, если это возможно, чтобы понять его как можно лучше!

Another Dude 17.05.2022 20:15

это невозможно сделать со стандартными ViewModifiers. Вы можете создать свой собственный, а также пользовательский ViewModifier и Binding<Bool>, но вы потеряете свайп, особенно свайп с List. DragGesture будет мешать перетаскиванию List или ScrollView

lorem ipsum 17.05.2022 20:42
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
3
19
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, такой встроенной гибкости нет, скажем, в стандартном .sheet, но ее можно очень быстро реализовать на заказ.

Вот простая демонстрация (Xcode 13.3/iOS 15.4)

demo

Основная часть:

struct ElementsList: View {
// ...
        ModalView(isPresented: $isModal) {
            List(elements, id: \.self) {


struct ModalView<V: View>: View {
    @Binding var isPresented: Bool
// ...
        ZStack {
            content()
            ZStack {
                VStack {
                    if isPresented {
                        Color.black.opacity(0.8)
                            .transition(.opacity)
                    }
                }.animation(.easeInOut(duration: 0.25), value: isPresented)


Полный тестовый код в проекте находится здесь

Спасибо @Аспери!

Another Dude 17.05.2022 22:58

Другие вопросы по теме

SwiftUI: как сделать так, чтобы представление исчезало при скольжении вверх?
SwiftUI: как создать собственный переход SwiftUI в зависимости от объекта состояния?
Как заполнить все возможные столбцы в фрейме данных с помощью r data.table?
Поведение перехода оператора SwiftUI Switch не соответствует ожидаемому
Как добавить заголовок вторичной строки в выходную таблицу со встроенным реактивным объектом?
Как добавить реактивный объект в заголовок вторичного столбца в выходной таблице?
Как изменить этот код data.table, чтобы отображались переходы баланса вместо переходов частоты событий?
Как отформатировать таблицу с дополнительными заголовками столбцов и строк, включая вертикальное выравнивание и реактивные входы?
Как создать таблицу, измеряющую переходы элементов за календарные периоды?
Как изменить ширину справа налево, а не слева направо по умолчанию?