【问题标题】:NavigationView frame glitch with safearea带有安全区域的 NavigationView 帧故障
【发布时间】:2021-08-17 16:44:56
【问题描述】:

我尝试创建一个类似于 SwiftUI 的 .sheet 修饰符的自定义 ViewModifier。

当我尝试让 NavigationView 从底部弹出时,视图的框架刚刚在安全区域上出现故障。当视图从底部移动到顶部时,框架看起来好像调整到安全区域。

有人知道如何限制导航视图内的视图框架以避免这种情况吗?

这就是发生的事情。单击加号按钮时,会显示 SwiftUI .sheet 修饰符。按下齿轮按钮时会出现自定义弹出窗口。 Problem gif recording here

这是自定义弹出视图的代码。

struct SettingsView: View {
    @Binding var showingSelf: Bool
    @Binding var retryWrongCards: Bool
        
    var body: some View {
        GeometryReader { geometry in
            NavigationView {
                List {
                    Section {
                        Toggle(isOn: $retryWrongCards) {
                            Text("Retry Wrong Cards")
                        }
                    }
                }
                .animation(nil)
                .navigationViewStyle(StackNavigationViewStyle())
                .listStyle(GroupedListStyle())
                .navigationBarTitle("Settings")
                .navigationBarItems(trailing: Button("Done") {
                    self.showingSelf = false
                })
            }
        }
    }
}

这是自定义修饰符的代码

struct Popup<T: View>: ViewModifier {
    let popup: T
    let isPresented: Bool

    init(isPresented: Bool, @ViewBuilder content: () -> T) {
        self.isPresented = isPresented
        popup = content()
    }

    func body(content: Content) -> some View {
        content
            .overlay(popupContent())
    }

    @ViewBuilder private func popupContent() -> some View {
        GeometryReader { geometry in
            if isPresented {
                popup
                    .animation(.spring())
                    .transition(.offset(x: 0, y: geometry.belowScreenEdge))
                    .frame(width: geometry.size.width, height: geometry.size.height)
            }
        }
    }
}

private extension GeometryProxy {
    var belowScreenEdge: CGFloat {
        UIScreen.main.bounds.height - frame(in: .global).minY
    }
}

【问题讨论】:

  • 您似乎没有使用几何阅读器...
  • 目前还不清楚您的意思是什么“故障”以及它是否与您的自定义工作表修饰符或未使用的 GeometryReader 有关。也许您还发布了自定义工作表修饰符的代码?它是基于 Apples sheet 修饰符吗?或者您只是用.transition(.move(edge: .bottom)) 修饰符覆盖屏幕(使用GeometryReader)?
  • @pd95 嗨,我在按下齿轮按钮时指的是 NavigationView。我试图用geometry.size.width 解决这个问题,但NavigationBarItem 仍然与安全区域重叠。动画时,视图会水平收缩,然后再次展开。我正在使用 .transition() 来移动视图。我在上面添加了视图修饰符代码。
  • 嗨,本,我的另一个问题 :-)。我看到您正在以横向模式在 iPhone 11/12 上进行测试。因此,您希望左侧和右侧的“安全区域”得到尊重,这在您的“EditCards”屏幕中就是这种情况,但在“设置”屏幕中却不是。所以我有以下问题:您的 EditCards 屏幕是否使用您的自定义工作表修饰符?还是只有设置屏幕使用修饰符?进一步:您是在设备上进行测试还是仅在模拟器中进行测试?
  • 嗨@BenLin,我想我可以在我自己的“FlashZilla”版本中可靠地重现您的问题,并且可以确认在弹出窗口的转换(输入或输出)期间,@987654327 的内容@ 不尊重安全区域插图。对我来说,它们只有在过渡完成动画后才会“弹出”。常规的 .sheet 修饰符不会发生这种情况。

标签: swift xcode swiftui


【解决方案1】:

在调试并尝试了许多更改之后,我已经准备了一个小项目来为 Apple 提交 SwiftUI 错误。最后,没有必要,我们有一个简单的解决方案?!!

TLDR;您的SettingsView 未正确初始化NavigationView
修饰符 .navigationViewStyle(StackNavigationViewStyle()) 必须应用于 NavigationView 而不是在其内部(与 navigationBarTitlenavigationBarItems 相比,它们仅在放入 NavigationView 时才有效):

NavigationView {
    List {
        Section {
            Toggle(isOn: $retryWrongCards) {
                Text("Retry Wrong Cards")
            }
        }
    }
    .animation(nil)
    .listStyle(GroupedListStyle())
    .navigationBarTitle("Settings")
    .navigationBarItems(trailing: Button("Done") {
        self.showingSelf = false
    })
}
.navigationViewStyle(StackNavigationViewStyle())

在此更改之后,您的自定义工作表修饰符对我而言与常规 .sheet 修饰符的行为相同!做得好! 菲利普

【讨论】:

  • 这很完美!谢谢!它现在看起来和 .sheet 修饰符一模一样。
【解决方案2】:

您的动画似乎与工作表完全一样。我会用那个代替它。您可以轻松地在工作表上显示工作表。

编辑

在您发布 ViewModifier 代码后,似乎唯一的区别是动画类型和弹出窗口的大小。

【讨论】:

  • 对...我正在尝试构建一个自定义弹出视图修改器,以便我可以在具有不同过渡动画的不同地方使用它。
猜你喜欢
  • 2018-06-09
  • 1970-01-01
  • 2021-01-24
  • 1970-01-01
  • 2012-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多