SwiftUI HStack以相等的间距填充整个宽度

Tim*_*Tim 46 ios swift swiftui

我有一个 HStack:

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

如何以相等的间距将其内容完美地居中并自动填充整个宽度?

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

sva*_*all 106

可以使用frame带有.infinityformaxWidth参数的布局修饰符来实现这一点,而无需额外的ShapeView。

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)
            }
        }
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 .frame 修饰符进行比较


kga*_*dis 27

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()
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

即使项目宽度不同,示例列表也会均匀分布: 在此输入图像描述

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

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

Joh*_* M. 15

各个*Stack类型将尽量缩到最小尺寸可以容纳他们的孩子的意见。如果子视图具有理想的大小,则*Stack不会扩展以填满屏幕。这可以通过将每个孩子放在 aRectangle中的空白之上来克服ZStack,因为 aShape会尽可能地扩大。一个方便的方法是通过扩展View

extension View {
    func inExpandingRectangle() -> some View {
        ZStack {
            Rectangle()
                .fill(Color.clear)
            self
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样称呼它:

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)
                }
            }

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

非扩展和扩展堆栈

  • 不需要额外的形状,您只需要为具有 .infinity 值的子视图添加 .frame 修饰符,以便它扩展以填充父级宽度。请检查@svarrall 的答案 (2认同)

Moj*_*ini 13

如果项目是全角兼容的,它将自动完成,您可以将项目包裹在间隔符之间以实现它:

struct Resizable: View {
    let text: String

    var body: some View {
        HStack {
            Spacer()
            Text(text)
            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

单视图

那么你。可以在循环中使用它,例如:

HStack {
    ForEach(data, id: \.self) { item in
        Resizable(text: item)
    }
}
Run Code Online (Sandbox Code Playgroud)

多视图

  • 对此的改进可以是: ``` struct Resizable<Content: View>: View { let content: () -> Content var body: some View { HStack { Spacer() content() Spacer() } } } `` ` (2认同)

Wah*_*don 8

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

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

输出结果看起来像这样...

在此输入图像描述


al0*_*00p 5

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

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