Родительский вид игнорирует безопасную зону, но дочерний вид соблюдает безопасную зону

Я создаю собственную полноэкранную обложку, которую можно перетаскивать жестом, как в приложении подкаста.

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

Проблема в том, что я хочу, чтобы элементы полноэкранного покрытия, такие как текст и кнопки, соответствовали безопасной области, за исключением ее фона.

Я не уверен, как это исправить. Каждое отдельное решение по stackoverflow совершенно не имеет значения, поскольку они предлагают использовать модификатор фона, не принимая во внимание использование модификаторов, таких как переход с краем в качестве нижнего.

struct Tabs: View {
     @State private var showingCover = false

     var body: some View {

        ZStack {
            TabView {
                ...
            }
            
            if showing {
                FullScreenCover(showingCover: $showingCover)
                    .zIndex(1)
                    .transition(.move(edge: .bottom))
            }
        }
        .ignoresSafeArea() //I need to set this here so that the bottom edge recognised by the transition modifier would be the very bottom edge of the device. 
    }
}

struct FullScreenCover: View {
    @Binding var showingCover: Bool
    @State private var offset: CGFloat = 0.0

    var body: some View {
        ZStack(alignment: .bottom) {
            //Blue color is the background
            Color.blue
                .ignoresSafeArea()
            
            //Other elements like text must respect safe area
            Text("Hello")
        }
        .offset(y: offset)
        .gesture(
            DragGesture(minimumDistance: 1)
                .onChanged { value in
                    if value.translation.height > 0 {
                        withAnimation(.smooth(duration: 0.1)) {
                            //Drag cover vertically based on drag gesture
                            offset = value.translation.height
                        }
                    }
                }
                .onEnded { value in
                    if value.predictedEndTranslation.height < 200 {
                        withAnimation(.smooth()) {
                            //Pop cover back fully
                            offset = 0
                        }
                    } else {
                        withAnimation(.smooth()) {
                            //Dismiss cover to the bottom of the screen
                            showingCover = false
                            offset = 0
                        }
                    }
                }
        )
    }
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мне до сих пор непонятно, почему вы не можете использовать .fullScreenCover? Жест перетаскивания также можно использовать для этого контента. Вам просто нужно установить фон презентации на Color.clear, чтобы можно было видеть базовый вид.

struct ContentView: View {
    @State private var showingCover = false
    var body: some View {
        TabView {
            Button("Show full screen cover") {
                showingCover.toggle()
            }
        }
        .fullScreenCover(isPresented: $showingCover) {
            FullScreenCover(showingCover: $showingCover)
                .presentationBackground(.clear)
        }
    }
}

Animation

@SwiftUIEnthusiast Еще одна попытка с .fullScreenCover. Почему именно вы не можете использовать этот подход?

Benzy Neez 25.07.2024 16:27

Если я не ошибаюсь, .presentationBackground(.clear) требует iOS 16.4 и более поздних версий, но мне нужна поддержка до iOS 16 и более поздних версий. Но ваше решение также справедливо.

SwiftUIEnthusiast 25.07.2024 16:31

И после тестирования вашего решения, одним из основных недостатков является то, что когда вы перетаскиваете обложку ниже безопасной области и пытаетесь перетащить ее в безопасную область в верхней части iPhone, фон обложки «застревает»/«застревает» прямо в месте. граница безопасной зоны.

SwiftUIEnthusiast 25.07.2024 17:09
Ответ принят как подходящий

Решение, к которому я пришел после тестирования различных других решений в течение недели, заключается в чтении вставок безопасной области родительского представления представления вкладок (т. е. в моем случае это ContentView или даже структура приложения, которая также работает), а затем внедрение этого в окружающая среда.

Затем прочитайте вставки безопасной области из среды в представлении FullScreenCover и восстановите в нем заполнение вставок безопасной области.

struct SafeAreaInsetsKey: EnvironmentKey {
    static let defaultValue: EdgeInsets = EdgeInsets()
}

extension EnvironmentValues {
    var safeAreaInsets: EdgeInsets {
        get { self[SafeAreaInsetsKey.self] }
        set { self[SafeAreaInsetsKey.self] = newValue }
    }
}

var body: some Scene {
    WindowGroup {
        GeometryReader { geo in
            ContentView()
                .environment(\.safeAreaInsets, geo.safeAreaInsets)
        }
    }
}

struct FullScreenCover: View {
    @Environment(\.safeAreaInsets) var safeAreaInsets

    var body: some View {
        ZStack(alignment: .bottom) {
           //Blue color is the background
           Color.blue
              .ignoresSafeArea()
        
           //Other elements like text must respect safe area
           VStack {
              Text("Hello")
           }
           .padding(safeAreaInsets)
        }
    } 
}

Я рад представить и другие, более нативные решения.

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