Игнорирование безопасной зоны предотвращает нажатие кнопки

У меня есть собственный вид, в котором есть 3 страницы: синяя, красная и зеленая. Каждая страница занимает всю ширину экрана, и для перемещения между ними я использую жест перетаскивания по краю. Исходный вид — центральный, красный.

Если я перейду на синюю или зеленую страницы и либо: полностью открою лист, либо открою клавиатуру, то красная средняя страница больше не будет доступна для кликов. Однако левая и правая страницы по-прежнему доступны для кликов.

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

Размещение стека навигации в самом верху представления также исправляет ситуацию, но я этого не хочу. Удаление всех игнорируемых безопасных областей из стека навигации также исправляет это, но они мне нужны. Очень странное поведение: если отображается состояние неисправности клавиатуры и вы проводите пальцем по центральной странице, пока отображается клавиатура, центральная страница снова становится доступной для щелчка.

Чтобы воспроизвести: край Swift справа -> сфокусировать текстовое поле -> проведите по краю назад -> кнопка не должна быть кликабельной (дефект)

Код можно копировать и вставлять.

import SwiftUI

struct MainView: View {
    @Environment(\.colorScheme) var colorScheme
    @State var offset: CGFloat = 0
    @State var option: Int = 2
    @State var lastStoredOffset: CGFloat = 0
    @GestureState var gestureOffset: CGFloat = 0
    @State var scale: CGFloat = 0.7
    @State var content: Bool = false
    @State var text = ""
    
    var body: some View {
        HStack(spacing: 0){
            // PAGE ONE
            ZStack {
                Color.blue
                    .frame(width: widthOrHeight(width: true))
                    .scaleEffect(scale)
            }
            .frame(width: widthOrHeight(width: true))
            .ignoresSafeArea()
            
            // DIVIDER
            Color.blue.ignoresSafeArea().frame(width: 13)
            
            //PAGE 2 WITH DEFECT
            NavigationStack {
                ZStack {
                    Color.red
                    Button(action: {
                        
                    }, label: {
                        Text("Button").font(.title)
                    })
                }
                .ignoresSafeArea()
            }
            .frame(width: widthOrHeight(width: true))
            .ignoresSafeArea()
           
            //DIVIDER
            Color.blue.ignoresSafeArea().frame(width: 13)
 
            //PAGE 3           
            ZStack {
                Color.green
                TextField("insert", text: $text)
            }
            .frame(width: widthOrHeight(width: true))
            .ignoresSafeArea()
        }
        .offset(x: offset)
        .simultaneousGesture (
            DragGesture()
                .onChanged({ value in
                        let width = widthOrHeight(width: true)
                        let width2 = width * 2
                        
                        if option == 2 {
                            if (value.startLocation.x >= (width + 13) && value.startLocation.x <= (width + 28)) || (value.startLocation.x >= (width2 - 2.0) && value.startLocation.x <= (width2 + 13)) {
                                offset = value.translation.width + lastStoredOffset
                            }
                        } else if option == 1 {
                            if value.translation.width < 0 {
                                offset = value.translation.width + lastStoredOffset
                            }
                        } else {
                            if value.translation.width > 0 {
                                if value.startLocation.x >= (width + 13) && value.startLocation.x <= (width + 28.0) {
                                    offset = value.translation.width + lastStoredOffset
                                }
                            }
                        }
                        
                        let ratio = (abs(offset) / width) * 0.3
                        scale = 0.7 + min(0.3, max(0.0, ratio))
                })
                .onEnded({ value in
                        let width = widthOrHeight(width: true)
                        
                        if option == 1 {
                            if offset < (width * 0.6) || value.velocity.width < -400.0 {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = 0
                                    scale = 0.7
                                }
                                lastStoredOffset = 0
                                option = 2
                            } else {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = width + 13
                                    scale = 1.0
                                }
                                lastStoredOffset = width + 13
                            }
                        } else if option == 2 {
                            let leftstart: Bool = (abs(value.startLocation.x - width) < 100.0)
                            
                            if (offset > (width * 0.4) || value.velocity.width > 400.0) && leftstart {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = width + 13
                                    scale = 1.0
                                }
                                lastStoredOffset = width + 13
                                option = 1
                                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                            } else if (offset < -(width * 0.4) || value.velocity.width < -400.0) && !leftstart {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = -width - 13
                                    scale = 1.0
                                }
                                lastStoredOffset = -width - 13
                                option = 3
                                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                            } else {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = 0
                                    scale = 0.7
                                }
                                lastStoredOffset = 0
                            }
                        } else {
                            let isEdge: Bool = value.startLocation.x >= (width + 13) && value.startLocation.x <= (width + 28.0)
                            if offset > -(width * 0.6) || (value.velocity.width > 400.0 && isEdge) {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = 0
                                    scale = 0.7
                                }
                                lastStoredOffset = 0
                                option = 2
                            } else {
                                withAnimation(.easeInOut(duration: 0.15)){
                                    offset = -width - 13
                                    scale = 1.0
                                }
                                lastStoredOffset = -width - 13
                            }
                        }
                })
            
        )
    }
}

func widthOrHeight(width: Bool) -> CGFloat {
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    let window = windowScene?.windows.first
    
    if width {
        return window?.screen.bounds.width ?? 0
    } else {
        return window?.screen.bounds.height ?? 0
    }
}

#Preview {
    MainView()
}


func top_Inset() -> CGFloat {
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    let window = windowScene?.windows.first
    
    return window?.safeAreaInsets.top ?? 0
}

func bottom_Inset() -> CGFloat {
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    let window = windowScene?.windows.first
    
    return window?.safeAreaInsets.bottom ?? 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Решение, которое я нашел, заключалось в применении .zIndex(1) к первой и третьей страницам, а .zIndex(500) к средней странице. Похоже, что клавиатура влияет на безопасную область, поэтому сочетание NavigationStacks и IgnoreSafeAreas может вызвать проблемы.

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