【问题标题】:Position view bottom without using a spacer在不使用垫片的情况下定位视图底部
【发布时间】:2019-12-03 20:50:52
【问题描述】:

如何在不使用垫片的情况下将视图定位在底部。我知道我可以在 VStack 中放置一个垫片和我的视图来实现它,但我不想使用垫片,因为我不希望我的视图占据所有垂直空间。使用 UIKit,我会将其放置在安全区域底部指南中。

【问题讨论】:

    标签: position swiftui


    【解决方案1】:

    我认为最简单的方法是为container 视图添加一个框架。

    Group{ // container View
        Text("iner label")
    }.frame(maxHeight: .infinity, alignment: .bottom)
    

    如果不加frame,默认frame会包裹inner view,大小和inner View一样。如果添加一个框架,它会创建一个属于外部视图的空间,在 UIView 概念中,它是一个超级视图。然后你会看到你需要处理什么。

    【讨论】:

      【解决方案2】:

      尝试不同的方法后,我最终创建了自己的自定义容器,它有一些已知的限制,完全满足了我的需求。希望对其他人有帮助。

      演示:

      优点:ContentView 和 PinnedView 在布局上完全独立,自动处理设备方向,内部内容实际上是无限的

      缺点:由于在顶级内容或固定视图中使用GeometryReader 使用.infinity 导致由于“鸡蛋”问题而崩溃。

      容器代码:

      struct ContainerWithPinnedBottomView<Content, Pinned>: View 
                                           where Content: View, Pinned: View {
      
          private var content: () -> Content
          private var bottomView: () -> Pinned
      
          @inlinable public init(@ViewBuilder pinnedView: @escaping () -> Pinned,
                                  @ViewBuilder content: @escaping () -> Content) {
              self.content = content
              self.bottomView = pinnedView
          }
      
          var body: some View {
              ZStack(alignment: .bottom) {
                  Rectangle().fill(Color.clear) // !! Extends ZStack to full screen
                  GeometryReader { _ in
                      ZStack {
                          self.content()
                      }
                  }
                  self.bottomView()
                      .alignmentGuide(.bottom) { $0[.bottom] }
              }
          }
      
      }
      

      使用示例(演示截图)

      struct TestBottomView: View {
          var body: some View {
              ContainerWithPinnedBottomView(pinnedView: {
                  HStack {
                      Spacer()
                      Text("Always Pinned to Bottom")
                          .padding()
          //                .frame(width: .infinity) // !! LIMITATION - don't use, cycling crash
                      Spacer()
                  }
                  .background(Color.blue)
              }) {
                  NavigationView {
                      List (0 ..< 100, id: \.self) { i in
                          NavigationLink(destination: Text("Other")) {
                              Text("Row \(i)")
                          }
                      }
                      .navigationBarTitle("TitleBar")
                  }
              }
          }
      }
      
      struct TestBottomView_Previews: PreviewProvider {
          static var previews: some View {
              TestBottomView()
          }
      }
      

      【讨论】:

        【解决方案3】:

        Position 属性将帮助您尝试这种方式

        Group{ // container View
             Text("iner label")
        }.position(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height-50)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-28
          • 2019-03-06
          • 2021-03-25
          • 1970-01-01
          • 2017-11-18
          • 1970-01-01
          相关资源
          最近更新 更多