【问题标题】:SwiftUI HStack fill whole width with equal spacingSwiftUI HStack 以等间距填充整个宽度
【发布时间】:2020-03-12 05:26:30
【问题描述】:

我有一个 HStack:

struct BottomList: View {
    var body: some View {
        HStack() {
            ForEach(navData) { item in
                NavItem(image: item.icon, title: item.title)
            }
        }
    }
}

如何以等间距自动填充整个宽度,使其内容完美居中?

仅供参考,就像 Bootstraps CSS 类 .justify-content-around

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    frame 布局修饰符,.infinity 用于maxWidth 参数可用于实现此目的,无需额外的Shape 视图。

    struct ContentView: View {
        var data = ["View", "V", "View Long"]
    
        var body: some View {
        VStack {
    
            // This will be as small as possible to fit the data
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .border(Color.red)
                }
            }
    
            // The frame modifier allows the view to expand horizontally
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .frame(maxWidth: .infinity)
                        .border(Color.red)
                }
            }
        }
        }
    }
    

    【讨论】:

      【解决方案2】:

      各种*Stack 类型将尝试缩小到可能包含其子视图的最小尺寸。如果子视图具有理想的大小,则*Stack 将不会扩展以填满屏幕。这可以通过将每个孩子放在ZStack 中的明确Rectangle 之上来克服,因为Shape 将尽可能地扩展。一个方便的方法是通过View 上的扩展:

      extension View {
          func inExpandingRectangle() -> some View {
              ZStack {
                  Rectangle()
                      .fill(Color.clear)
                  self
              }
          }
      }
      

      你可以这样称呼它:

      struct ContentView: View {
          var data = ["View", "View", "View"]
      
          var body: some View {
              VStack {
      
                  // This will be as small as possible to fit the items
                  HStack {
                      ForEach(data, id: \.self) { item in
                          Text(item)
                              .border(Color.red)
                      }
                  }
      
                  // Each item's invisible Rectangle forces it to expand
                  // The .fixedSize modifier prevents expansion in the vertical direction
                  HStack {
                      ForEach(data, id: \.self) { item in
                          Text(item)
                              .inExpandingRectangle()
                              .fixedSize(horizontal: false, vertical: true)
                              .border(Color.red)
                      }
                  }
      
              }
          }
      }
      

      您可以根据需要调整HStack 上的间距。

      【讨论】:

      • 不需要额外的形状,您只需要为具有 .infinity 值的子视图添加 .frame 修饰符,使其扩展以填充父宽度。请检查@svarrall 答案
      【解决方案3】:

      我在每一项之后都插入了Spacer()...但对于最后一项,请添加Spacer()

      struct BottomList: View {
          var body: some View {
              HStack() {
                  ForEach(data) { item in
                      Item(title: item.title)
                      if item != data.last { // match everything but the last
                        Spacer()
                      }
                  }
              }
          }
      }
      

      即使项目宽度不同也均匀分布的示例列表:

      (注意:接受的答案 .frame(maxWidth: .infinity) 并不适用于所有情况:当涉及到具有不同宽度的项目时,它不适用于我)

      【讨论】:

      • 虽然我不喜欢它,但使用 .frame(maxWidth: .infinity) 并没有给我想要的外观,因为它增加了 for each 中每个对象的框架,而不是将它们保持在定义的大小。这增加了我正在寻找的对象之间的间距。
      【解决方案4】:

      如果项目是全宽兼容的,它将自动完成,您可以在间隔符之间包裹项目以使其发生:

      struct Resizable: View {
          let text: String
      
          var body: some View {
              HStack {
                  Spacer()
                  Text(text)
                  Spacer()
              }
          }
      }
      

      所以你。可以在循环中使用它:

      HStack {
          ForEach(data, id: \.self) { item in
              Resizable(text: item)
          }
      }
      

      【讨论】:

        【解决方案5】:

        您也可以在堆栈中使用spacing ...即

        HStack(spacing: 30){
                    
                    Image("NetflixLogo")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 40)
                    
                    Text("TV Show")
                    Text("Movies")
                    Text("My List")
                    
                }
        .frame(maxWidth: .infinity)
        

        输出结果如下...

        【讨论】:

          【解决方案6】:

          如果您的数组有重复值,请使用 array.indices 在最后一个元素后省略一个分隔符。

          HStack() {
            ForEach(data.indices) { i in
              Text("\(data[i])")
              if i != data.last {
                 Spacer()
              }
            }
          }
          

          【讨论】:

            猜你喜欢
            • 2021-04-24
            • 2020-07-28
            • 1970-01-01
            • 2021-12-18
            • 2022-01-25
            • 2019-10-23
            • 2015-02-06
            • 1970-01-01
            • 2017-04-13
            相关资源
            最近更新 更多