如何在 SwiftUI 中使用 edgeIgnoringSafeArea,但让子视图尊重安全区域?

goh*_*tis 40 ios swiftui

我正在构建一个带有列表视图的 SwiftUI UI,我想在列表视图的一部分上放置一个面板,上面有一个按钮。

在底部有安全区域(没有物理主页按钮)的设备上,我希望面板转到屏幕底部。但我想确保面板上的按钮不会延伸到安全区域。

在我的示例代码中,HStack是包含按钮的面板。我尝试添加.edgesIgnoringSafeArea(.bottom)它,但这不允许它扩展到底部。这让我有点困惑,因为同一个列表ZStack延伸到底部安全区域。

当我添加.edgesIgnoringSafeArea(.bottom)到 时ZStackHStack允许(蓝色面板)延伸到屏幕底部的安全区域。这就是我想要的,但那么一旦我这样做,我怎么能告诉Button那个年代的孩子HStack忽视安全区?

我知道如何在 UIKit 中执行此操作,但我真的希望能够在 SwiftUI 中构建此 UI。我可以手动添加一些填充或间隔以Button在安全区域下添加额外的填充,但随后在没有底部安全区域的带有主页按钮的设备上会有额外的间距。我想找出一个优雅的解决方案,我可以依靠系统来定义其安全区域,而不是手动定义任何数字间距或为不同设备创建条件情况。

struct ContentView: View {
    var body: some View {

        ZStack(alignment: .bottom) {

                    List {
                        Text("Item 1")
                        Text("Item 2")
                        Text("Item 3")
                    }

                    HStack {
                        Spacer()
                        Button(action: {
                            // do something
                        }){
                            Text("Button")
                                .font(.title)
                                .padding()
                                .background(Color.green)
                                .foregroundColor(.white)
                                .cornerRadius(15)
                        }.padding()
                        Spacer()
                    }.background(Color.blue).edgesIgnoringSafeArea(.bottom)
                }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要的失败尝试的屏幕截图

Joe*_*ick 87

无论您在背景修改器中绘制什么视图,都将使用它正在修改的视图的框架。所以你需要告诉那个视图忽略安全区域。

.background(Color.blue.edgesIgnoringSafeArea(.bottom))
Run Code Online (Sandbox Code Playgroud)

  • 最佳答案。这让我很生气,因为这不被接受 (6认同)
  • 是的,非常有帮助:) (2认同)

Kev*_*inP 24

您可以使用 GeometryReader 访问安全区域的高度。然后您可以使用安全区域的高度作为按钮的底部填充或偏移。
https://developer.apple.com/documentation/swiftui/geometryproxy

struct ContentView: View {
    var body: some View {

        GeometryReader { proxy in
            ZStack(alignment: .bottom) {

                List {
                    Text("Item 1")
                    Text("Item 2")
                    Text("Item 3")
                }

                HStack {
                    Spacer()
                    Button(action: {
                        // do something
                    }){
                        Text("Button")
                            .font(.title)
                            .padding()
                            .background(Color.green)
                            .foregroundColor(.white)
                            .cornerRadius(15)
                    }
                    .padding(.bottom, proxy.safeAreaInsets.top)
                    Spacer()
                }.background(Color.blue)
            }.edgesIgnoringSafeArea(.bottom)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在 NavigationView 中不起作用,也是一个糟糕的答案(请参阅@Joe Susnick 的答案)。 (4认同)
  • 不幸的是,使用 GeometryReader 可能会产生各种间距问题......它会扩展以占用所有可用空间。 (2认同)

小智 9

edgesIgnoringSafeArea(_:)弃用

使用以下内容:

.background(Color.blue.ignoresSafeArea(edges: .bottom))
Run Code Online (Sandbox Code Playgroud)